シンプルな分散ジョブスケジューラを作ってみた #appkoyomi
掲題の通り、軽量動作する分散ジョブスケジューラを作ってみました。
名前は Koyomi としました。
Perl で書きました。CPAN にもアップしています。*1
Motivation
出発点となった課題感としては、だいたい cron の冗長化法について調べてみた #cron - weblog of key_amb という記事に書いた通りです:
- バッチサーバの冗長化は割と見過ごされやすい
- やろうとするとちょっと面倒
上の記事では cron を冗長化するやり方をいくつか紹介したのですが、NFS は SPOF になりやすいし、keepalived を使ったやり方もなんだかトリッキーで少し複雑な気がしないでもないです。
そこで、もっとシンプルに高可用性を達成するやり方はないかなと考えて、実装してみました。
動作原理
仕掛けは割と単純で、スケジュールのデータストアをスケジューラ・ワーカーから分離する、というアプローチです。
データストアとしては今は MySQL しか対応してないのですが、将来的にいろんなデータストアをサポートできたらいいかな、と思っています。
同一クラスタ内のワーカー(=koyomiプロセス)は同じ設定・スケジュールで動作する前提です。
ワーカーを動かすサーバは今のところ 2, 3 台あれば十分でしょう。
スケジューリングされたジョブは一度に1回だけ実行される想定なので、複数台のワーカーで同じジョブが同時に実行されないように制御する必要があります。*2
どうしたらいいかというと、まあミューテックスを取ればいいだろうと思いました。
つまり、先に動いた方がミューテックスを獲得してジョブを実行し、ミューテックスを獲得できなかった方は諦める、ということです。
Redisでバッチ処理を冗長化しつつ排他制御 - SSSSLIDE このスライドでは、同じ発想で Redis 上にミューテックスを用意して Rails のバッチサーバを冗長化する例が上げられています。
また、以前に RunDeck というジョブスケジューラでも、ちょっと変わった工夫をすればこういうことができそうだと書きました。*3
Road to v1.0
いま v0.1.4 なのですが、 v1.0 までにやりたいなと思っていることをドキュメントサイトの MILESTONE に書いておきました。
興味を持ってくださった方へ
上の MILESTONE に書いたようなことが実現されるまでちょっと使いづらいところがあるかなと思いますが、「こういうのほしかった」という人がいたらうれしいです。
フィードバック歓迎します。
落ちたら困るジョブをお持ちの方は、お見知りおき頂ければ幸いです。
※CPAN に壊れたモジュールを上げてたら早速「動かないよ」とご指摘いただきました。*4
すいませんすいません。
余談
実は最初は CPAN に上げるつもりなかったです。
DB とかいろいろ依存してるし、ライブラリじゃなくてアプリケーションだし、と思ったので。
そしたら偉い人から「上げない理由ないでしょ」と言われたので、「じゃあ上げます」と上げることにしました。
追記
ハッシュタグ悩んでたのですが、#appkoyomiにしました。
*1:https://metacpan.org/pod/App::Koyomi
*2:一度に2回以上ジョブを実行するような機能もつけれなくはないだろうけど、しばらくつける気はない。
*3:Rundeck によるバッチ実行サーバの冗長化について考えてみた、試してみた #Rundeck - weblog of key_amb