これまで GreenBuckets では、オブジェクトの読み込み時はノードがダウンした場合でも可用性が保たれていましたが、書き込みはオンライン状態にあるノード数がレプリカ数分ないと新規オブジェクトの追加ができませんでした。そのため可用性を保とうと思うと、レプリカ数が2では最低4台、レプリカ数3では最低6台のノードがないと1台でもノードがダウンした場合に書き込みができない状態になっていました。
これでは初期投資が大きくなりすぎるということで、最低2台(レプリカ数2)でも書き込みの冗長性が確保できるようにしてみた。
左の図が、ノード1が障害でオフラインの状態。これまでだとノード1に書き込もうとして失敗するとすぐに保存エラーとクライアントに返していましたが、GreenBucketsを変更して右の図のように、ノード2と3に仮に保存して(1)、新しく設けた Recovery Queue に登録します(2)。Recovery Queueはキュー登録から10分以上経過したところで動きだし、ノード1、2、3のうちからオブジェクトを探し出し(3)、再度保存をかけます(4)。保存にしっぱいしたらキューを戻し10分毎に確認させます。
これでMySQLに障害がなければ保存時に必要なレプリカが確保できなくても、仮でオブジェクトを保存し、ノード復旧後にレプリカを作成するようになりました。
追加で、GreenBucketsに対していくつか変更していて、Queue数が取れるようになっていたり、GETリクエストの情報がノードまで届くようになっています。
Queue数は、JobQueueのstats経由で取得できます。
> telnet localhost 5101
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Uptime: 231
BusyWorkers: 0
IdleWorkers: 7
ObjectsMaxID: 200
BucketsMaxID: 1
Queue: 30
RecoveryQueue: 0
JobQueueはデフォルトで5101ポートにてstatusが取れるサーバを立ち上げますが、そこに情報を追加しました。Queue数は監視サーバに登録しておくといいでしょう。他にもObjectsテーブルの最大値もあるので、作成されたオブジェクト数をCloudForecastなどでグラフ化していくのも面白いかもしれません
あと、オブジェクト取得時のGETのQUERY_STRINGがノードまで届くようになっていたり、元のURIのPATHをuri_escapeし、X-GreenBuckets-Original-Pathヘッダに追加しています。ノード側でごにょごにょ処理をいれたい場合は便利なはず。