CassandraとQuorumの話、というか、ある意味パラメータチューンかもしれない。

Your Ideal Performance: Consistency Tradeoff | DataStaxにとても面白い記事が載ってます。

Cassandraでは、一貫性(データ工学の文脈ではなく、CAP定理のConsistencyの意味)のレベルを変更できて、CAP定理で言うところの、CP(Bigtable)<->CA(Dyanamo)を行き来るのかなと思っています(Cassandraのプロトコル未調査なんですが)。

こういったことを知ると、気になるのはどのようなユースケースの場合に、この比率(Quorumでいう、R:W3や、2:1<3、1:2<3の場合に、どのような挙動をするのかを明確にしようという試みが今回紹介する記事ではされています。感覚的には分かるわけですね、R:W=1:3>3であれば、Read要求は1つのレプリカがYesを返せば、採用。Write要求は三つのレプリカがYesを返さない限り破棄。よって、この設定の場合はかなり、Read要求がWrite要求を邪魔しやすいのかなと思う。

R:W=1:2<3 であれば、1:1ほどでないにせよ、「強い一貫性」が失われます。この時、書込み後の経過時間に着目し、その経過時間に応じて読み込みの一貫性(言い換えると、どれくらい経てば、最新の情報をゲット出来るのか)がどのように変化するのかを知ることが出来れば設計段階でパラメータを設定できる。なければ、色々と実機で試さないといけない。これが課題意識。

ユーザには、様々な人がいるわけで、以下のようなニーズと設定があったりします。

  • データロストを絶対にしたくない&一貫性を担保したい人(R,W,N=3,3,5)
  • とにかく安く済ませたい&一貫性も担保したい人(R,W,N=1,1,1)
    • ただし、可用性が担保されていないわけですね。
  • データロストしたくない&スループット重要(1秒あたり100万オーダーの書き込み)&でもコストダウンしたい
    • でさらに、read要求の一貫性が50ms以内に90%、250ms以内に99.9%が満たされること。分かりづらいですが、read要求をしたときに、5更新後50ms経過していた場合、90%が最新という意味かなと思います。EvetualConsistencyだと、誤解を恐れずにいうなら、Uncommitted readみたいなことも起こるけですが、その時にどのくらい待てば、ほとんどそれが生じないかを要件として定義しているわけですね。
    • ここで、1000台のノードがあって、10日に1台は故障するとします。うーん、ちょっと見積もりが甘いかな。そうなると、N=1なんてことはできなくなります。
    • N=5はコストが高いので、N=3にするとすると、以下の組み合わせが出てきます。
R W N Comment
2 2 3 強い一貫性を保証しているが、50ms以内に90%が最新という緩めた要件に比べると強い
1 1 3 早いけど、もろにEventual Consistencyが発動するので、衝突がよく起こると思う
1 2 3 Read/Writeが衝突したときにReadの方が勝ちやすい、かつ、StrongConsistencyがなくなるが、1:1ほどではない
2 1 3 Read/Writeが衝突したときにWriteの方が勝ちやすい、かつ、StrongConsistencyがなくなるが、1:1ほどではない

と、定性的には分かるけど、定量的にそれぞれの設定の場合にRead要求の結果が最新になるまでの時間って、どれくらいかかるのかが気になりますよね。それに対して、モンテカルロ法をベースにシュミレータを作成した方々居ます。面白いですねー。

で、このシュミレータでは、R,W,Nを設定してあげると、write要求をしたあとにどれくらい経てば、readが出来るのかのグラフが出てきます。

とここまで来て、元々分かっていないCassandraのプロトコルがさらによくわからなくなってきた。ここまでの話は、私としてはレプリケーション管理のQuorum投票の話をしてきました。http://www.eecs.berkeley.edu/~pbailis/talks/bashochats-pbs.pdfを見てみたところ、Cassandra(もしかしたら、Dynamo?)では、W=2、R=1、N=3 が意味するのは、

  • 書き込み時は、書き込み要求を3つのレプリカに対して行い、二つのackが返ってきたら、ユーザにackを返却。
  • 読み込み時は、要求を3つに行い、一つでもデータ返却されたらそれをユーザに渡す。

ということで、合意プロトコルというよりも、実際にはcommitまでやっているようです。となると、W=3、R=1、N=3を考えると、R=1なので、書き込みを3つやっている途中状態を読み込んでしまう気がするんだけど、どうなんだろうか。後で思い出すために、課題だけ書いておこう。あるデータのレプリカをR1,R2,R3として、この時、R1からのみackがクライアントに返却されているとする。この時点で、R1が更新されているとすると、R1へのリード要求は、クラスタとしては書き込み完了されていないデータが返却される。

閑話休題、プロジェクトチームは、Hellerstein教授とFranklin教授のドリームチームですね。さすが過ぎ。