読者です 読者をやめる 読者になる 読者になる

中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

MongoDB製JOB Queue

お盆が暇だったので
MongoDB製Job queue を作った。
名前はMONMOちゃん

javascriptで手軽に使いたい部分があって個人用で考えていたが
結構マトモなモノが出来上がったので公開する事にする。

またMONMOちゃんを使って、自然言語処理も一式書いてみたが
こちらは次回紹介する。

注意

Javascriptではない。
MongoDB製だ!


繰り返し言おう。

MongoDBは環境である!!

About Monmoちゃん

github
https://github.com/monmo/monmo
概要
  • 全ての処理はMongoDB(mongod) 及び Mongo shell(mongo)上で動作する。
  • JobはJavascriptで記述する。
  • MongoDBへJob投入(制御データと実装)すると、予めどこかで起動したWorkerが処理する。
  • Job投入側にはスクリプトを用意した。
  • 現在のJobの種類
    • 通常Job
    • Map Job
    • MapReduceは実装作業中・・(emitを効率化できてなくて困ってる。。)
なぜ必要?

MongoDBにも以下の様なロジックを走らせる仕組みはある。

しかし、これらはサーバサイド(mongod)で走る。
OraclePL/SQLの様なモノだ。DBでアプリ処理を行えば割り食ってDBの性能が落ちる。
下手するとDB自体が落ちる!

なんの為に分散DB使ってるんだ!?
と・・・

そこでMongoDBクライアントであるMongo shell (mongo)を利用する事にした。
Mongo shellはMongoDBをオペレーションする時に不可欠なシェルだが、只のreadline程度のものじゃない。
V8搭載の高性能なJavascript実行環境だ!

MONMOちゃんの構成はこんな感じだ。

JOB


MAP


使い方

準備も利用も超簡単!

== 準備 ==
1. MongoDBを立てる。
2. MONMOちゃん一式をgit cloneする。(上記github
3. MONMOの設定ファイルにMongoDBのパスを指定
4. MONMOワーカーを立てる。

# ワーカーを4プロセス立てる
$ ./worker.sh -J 4

== JOB投入 ==
5. Job実装ファイルを作る

== samplejob.js ==
function main(jobctl,options) {
 jobctl.put( function(){
  return new Job({
   // Job投入側の処理
   //(
   //  サンプルなのでコレクションにデータを入れている
   //  本来はJOBの制御情報を作る処理になる
   //  )
   create_job : function(){
    this.src.drop();
    this.src.save({_id: 1,n:1});
    this.src.save({_id: 2,n:1});
    this.src.save({_id: 3,n:1});
    this.src.save({_id: 4,n:1});
    this.src.save({_id: 5,n:1});
    this.src.save({_id: 6,n:2});
    this.src.save({_id: 7,n:2});
    this.src.save({_id: 8,n:2});
    this.src.save({_id: 9,n:2});
    this.src.save({_id:10,n:2});
    return { ok:1 };
   },
   // Worker側で実行される処理(只のSUM)
   run : function(){
    var data = {i:0,n:0};
    this.src.find().forEach(function(doc){
     data.i += doc._id;
     data.n += doc.n;
    });
    this.dst.save(data);
    return {
     ok:1,
     msg: 'success',
     data: data
    };
   },
  });
 },options);
}

6. Jobを投入

# "test" DB "TEST"コレクションを入力側、"test" DB "RESULT"コレクションを出力側として指定
# 
$ ./jobctl.sh -s test.TEST -o test.RESULT  -f samplejob.js

7. 結果

- Load : ./sample/jobs/samplejob.js
{
   "_id" : ObjectId("5218092e241076268cbc9b71"),
   "args" : {
   },
   "dst" : "test.RESULT",
   "name" : "test.RESULT.job",
   "src" : "test.TEST",
   "st" : 1377306937204,
   "timeout" : 600000,
   "tm" : ISODate("2013-08-24T01:15:26.800Z"),
   "end" : ISODate("2013-08-24T01:15:27.209Z"),
   "ok" : 1,
   "msg" : "success",
   "data" : {
    "i" : 55,
    "n" : 15
   }
}