https://github.com/antirez/disque
disqueはRedisの作者が開発したメモリベースの分散メッセージブローカである。
- ゴールは
"Redis as a jobs queue"である。 - redisのようにシングルスレッドで動作する。 これはredis.ioにも言及されたように同じことだと思われる
- 現在のバージョンは1.0 betaでプロダクト環境にはまだ合わないかもしれないと書いてある。
disqueは分散され失敗に丈夫なメッセージブローカでメッセージを交換するためのプロセスの間に位置するミドルウェアとして動作する。
disqueではjobという単語を使っているが結局文字列のメッセージを意味するもので同じ意味で扱える。
disqueは順次的にコピーされるjob queueであって新しいjobが追加されるとW個のnodeにコピーされ、完了するとクライアントにjob idを返すようにしている。
disqueはat-least-onceとat-most-onceをサポートしている。
retry timeを0, replicateを1にするとat-most-onceになる。この際に必ずreplicateを1する必要はないがメッセージを複数個コピーする必要もないからだ。
その以外はat-least-onceになる
at-least-onceとat-most-onceはmessage毎に指定可能だ。
disqueはすべてのノードが同じ役割をする分散システムである(マルチマスタ) producerとconsumerはどんなnode接続しても構わないしロードとクライアントのリクエストによって自動でnode間でメッセージが交換される。
disqueはCAP Theoremのeventually consitent APに該当する。
disqueは信頼性を担保で低遅延非同期コマンドをサポートしている
メッセージを追加すると該当nodeに保存してそのままIDをクライアントに返し
バックグラウンドではnodo間のコピーが行われるのがその例だ。
こんな場合にコピーに問題なく完了されたか保証がないがクライアント側はリクエストの応答時間を減らせる
disqueはconsumerによって消費されたメッセージがACKされないと指定したretry時間後自動でrequeueされる機能持っている。
明示的にACKをするとメッセージは一回だけ転送される。
disqueはメッセージが生成される順で保存する時間はnodeの壁時計によって同じnode内では生成された順で転送される。
でもrequeue、auto-balancing、node間の時間差で順番が変わる場合があるがランダムで転送されることではない。基本的に先に入ったメッセージは先に転送されるようにしている。
disqueは各jobがfine-grained controlが出きるように三つの時間関連のパラメタは一つのコピー関連のパラメタを提供している。
(replicate, delay, retry, ttl)
disqueは永続化のためdiskに保存可能。
※ disqueはFIFOが厳しく守られてないため技術的に言うとメッセージキューと呼ばれるよりメッセージブローカ方が正しい。でもIT業界の観点ではメッセージキューとは一般的なブローカと軽く区別するために時々使わると思う。
クライアントは同じjobが複数回転送を防止するためACKを使用するとこができる。これはクライアントにメッセージが正常に転送されたことをdisqueに知らせるためである。
jobは複数のnodeに同じjob idでコピーされるが通常は一つのnodeに限ってqueuedの状態で存在する。 jobは4つ状態を持つが特にactiveかqueuedかを確認する。
GETJOBなどで消費されたメッセージはqueuedからactiveに状態が変わる。activeの状態のjobはキューに存在しないためまたGETJOBで拾えない。
ACKsメッセージによって確定(削除)されないとretry時間を過ぎたメッセージはrequeueされ状態はqueuedになってGETJOBなどで消費可能になる。
ENQUEUE/DEQUEUEコマンドで直接jobの状態をqueued/activeに変更できる。
disqueで使われてる一般的なACKはnode間で交換するコマンドが多くて処理費用が高い。
FASTACKは交換回数を減らしてオーバーヘッドが減らして高速化したものだ
半面ネットワーク上の問題であるnodeに削除コマンドが伝われてないことがあったらjobは再度消費される信頼性の問題が起きる可能性がある。
多くの場合メッセージキューはdead letter queueというものを実装している。これはメッセージが転送される度に失敗したり諸費される前にTTLを過ぎたりした場合など何らかの理由で処理出来ないメッセージを算出するための特別なキューのこと。
Append Only File(AOF)を使ってjobの生成と追放がdiskにロギングされ(with configurable fsync policies) 再起動時に再度ロードされる。
jobを識別するためのjob idは下記のように40文字の文字列になっていて
D-dcb833cf-8YL1NT17e9+wsA/09NqxscQI-05a1
また4つの部分で区別される
D- | dcb833cf | 8YL1NT17e9+wsA/09NqxscQI | 05a1
D-はprefixdcb833cfはメッセージが生成されたnodeのIDの頭から8バイト8YL1NT17e9+wsA/09NqxscQIは144bitのpseudo-random部分でbase64でエンコードされたもので/dev/urandomで生成されたseedとjob IDのカウントをSHA1にした上位の144bitを使用05a1はjobのTTLでjobを解析せずに破棄出来るようにするためである。