あ、どうも。ストレスが溜まって癒しを欲する今日この頃。ところでおれのPC、「いやし」を変換すると「嫌死」になるんだけど…。
3台構成のRiakクラスタを組んで一貫性レベルに応じた可用性の実験したという記事。一貫性レベル(Consistency level)についてなんだけど、Riakに限らずMongoDB(笑)やCassandra(墓)などの分散DBは同様の概念をもっている。これについてはある程度は馴染んでいるハズなんだけど、Riakは読み込みについてだけでもr(Read Quorum)に加えて、pr(Primary Read Quorum)など、ちょっと見慣れない(おれの知らない)パラメータがある。書き込みについてはw(write quorum), dw(durable write quorum), pw(primary write)と、実に3つのパラメータを使って一貫性を調整するようだ。とりあえずドキュメントベースでの調査と、簡単な実験行った。一貫性レベル、結果整合性のおおまかな説明は前々回の記事で書いたとおり。



0. ドキュメントベースの調査

公式ドキュメントのまんまだけど、おれの理解と不明点についてまとめる。下記の一貫性レベル関連のパラメータは、クエリごとに設定できる。設定がない場合は、バケットの設定の通りとなる。まぁ、オンライン処理のときは一貫性レベルをバケットにあらかじめ設定しておくのがいいかな。んで、まぁ調査を行う時や特別な一貫性レベルでアクセスを行いたいときだけ、明示的にクエリにパラメータをつけてやるのがいいんじゃないかと。

なお、下記に記載している「n_val」だけど、これはバケットごとのレプリケーション数のこと。これについても前々回の記事に簡単に説明が書いてある。

データ取得操作

  • r (read quorum)
    • オブジェクトを検索時に何個のレプリカが応答する必要があるか。
    • ‘one'(ひとつ)、’quorum'(過半数)、’all'(すべて)、’default’ (4294967295-4)、および N(n_val(※)以下の数値)が指定可能。
  • pr (primary read quorum)
    • 何個のプライマリ レプリカがオンラインである必要があるか
    • ‘one'(ひとつ)、’quorum'(過半数)、’all'(すべて)、’default’ (4294967295-4)、および N(n_val(※)以下の数値)が指定可能。
後述の実験の項目でも少しふれるが、どうやら「pr」がノードの生存数に応じた一貫性レベルを提供するっぽい。「r」をノードの生存数に変化させるとようわからん動きになった…。ちょっとまだ理解できてない。vnodeとかそのへんが関係してる?あと、プライマリレプリカって言葉の意味がよくわからん。

データ保存操作
  • w (write quorum)
    • 書き込み成功のレスポンスを返す前に、何個のレプリカに書き込む必要があるか。
    • ‘one'(ひとつ)、’quorum'(過半数)、’all'(すべて)、’default’ (4294967295-4)、および N(n_val(※)以下の数値)が指定可能。
  • dw (durable write quorum)
    • 書き込み成功のレスポンスを返す前に、何個のレプリカのストレージにデータをコミットする必要があるか。
    • ‘one'(ひとつ)、’quorum'(過半数)、’all'(すべて)、’default’ (4294967295-4)、および N(n_val(※)以下の数値)が指定可能。
  • pw (primary write)
    • 書き込みを行う前に、何個のプライマリ レプリカがオンラインである必要があるか。
    • ‘one'(ひとつ)、’quorum'(過半数)、’all'(すべて)、’default’ (4294967295-4)、および N(n_val(※)以下の数値)が指定可能。
取得操作のときと同様、「w」についてはよくわからないが、「pw」が生存しているノード数に応じた一貫性レベルを示している。「dw」は永続層への書き込みを保証する場合の一貫性レベルを指定する。「pw」の指定はメモリ上に書きこんで、書き込み成功とみなすが、「dw」はストレージに書きこんで、書き込み成功とみなすのではないかと。

データ削除
  • rw
    • get および put の両方で、削除するオブジェクトに関する指定を行う。
  • r (read quorum)
    • 取得操作の説明に同じ。
  • pr (primary read quorum)
    • 取得操作の説明に同じ。ただし、フォールバックノードであってはならない。
  • w (write quorum)
    • 保存操作の説明に同じ。
  • dw (durable write quorum)
    • 保存操作の説明に同じ。
  • pw (primary write quorum)
    • 保存操作の説明に同じ。
「rw」はよくわかんねえ。他については、取得/保存操作の説明と同じかな、と。

1. 一貫性レベルのテスト

適当なバケット「text」に書き込み/読み込みの操作を行ってみる。削除処理については省略。3台でクラスタを組んでいるのだが、1台ずつRiakプロセスを落としてみて挙動を調べる。結論から言うと、読み込み時は「pr」の指定が効いてくる。書き込みについては「pw」の指定が効いてくる。「dw」については調査しづらいのでやっていない。
まず、textバケットのプロパティをチェックしてみる。デフォルトだと、大抵はquorumになっている。レプリケーション数n_valは3。つまり、pr/pwにallを指定すると、3台すべて生存しているときのみ読み込み/書き込み処理に成功、pr/pwにquorumを指定すると、過半数(クラスタのノード数ではなく、レプリケーション数n_val=3の過半数)である2台が生存しているときに読み込み/書き込みが成功、pr/pwがoneのときは1台(略 となる。

curl -i http://localhost:8098/buckets/text/props

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"props": {
"young_vclock": 20,
"w": "quorum",
"small_vclock": 50,
"rw": "quorum",
"linkfun": {
"fun": "mapreduce_linkfun",
"mod": "riak_kv_wm_link_walker"
},
"last_write_wins": false,
"dw": "quorum",
"chash_keyfun": {
"fun": "chash_std_keyfun",
"mod": "riak_core_util"
},
"big_vclock": 50,
"basic_quorum": false,
"allow_mult": false,
"name": "text",
"n_val": 3,
"notfound_ok": true,
"old_vclock": 86400,
"postcommit": [],
"pr": 0,
"precommit": [],
"pw": 0,
"r": "quorum"
}
}

コマンドラインからは「curl -i “http://localhost:8098/buckets/xxx/keys/1?r=N&pr=N”」のようにクエリストリングに付与することで一貫性レベルを指示するのことができる。

書き込み
  • 3台構成で3/3が生存
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=all
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=quorum
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=one
  • 3台構成で2/3が生存
    • NG:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=all
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=quorum
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=one
  • 3台構成で1/3が生存
    • NG:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=all
    • NG:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=quorum
    • OK:curl -i -X PUT -H “Content-Type: text/plain” -d ‘aaaaaaaaaa’ http://localhost:8098/buckets/text/keys/2?pw=one
画面をキャプるのが面倒だったので味気ない感じになってしまったが、上記のとおりとなった。期待通りの動作。「w」の指定はよくわからん…。

読み込み
  • 3台構成で3/3が生存
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=all
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=quorum
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=one
  • 3台構成で2/3が生存
    • NG: curl -i  http://localhost:8098/buckets/text/keys/2?pr=all
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=quorum
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=one
  • 3台構成で1/3が生存
    • NG: curl -i  http://localhost:8098/buckets/text/keys/2?pr=all
    • NG: curl -i  http://localhost:8098/buckets/text/keys/2?pr=quorum
    • OK: curl -i  http://localhost:8098/buckets/text/keys/2?pr=one
上記のとおり、「pr」の指定に従って、一貫性/可用性が変化する。

2. 一貫性と可用性のトレードオフ

一貫性と可用性はトレードオフであることを示している。一貫性を強固にすると性能も落ちるだろうね。とりあえずは、WriteもReadもQuorumで運用するのがいいんじゃないかな。んで、書き込み「少」、読み込み「多」みたいな場合は、Write=All/Read=Oneみたいな感じで、ユースケースに応じて調整していきゃいいと思う。

今日はここまで。次はバックアップ/リストアのオペを実施してみる。

 

2 Responses to Riak 04 クラスタへのアクセスと一貫性レベル

  1. ponta より:

    PR/PWについて、

    http://lists.basho.com/pipermail/riak-users_lists.basho.com/2012-January/007157.html

    がわかりやすく思いました。

    http://docs.basho.com/riak/1.3.0/references/appendices/concepts/Replication/

    と合わせて読むと、レプリカを担う”V”ノードはPreflistという形で参照することができるようです。このうち、先頭のN分がプライマリーノード(レプリカ)、残りがフォールバックノードということじゃないのかな。

    で、プライマリーノードで必要なコピーが稼げなかったときには、フォールバックノードでレプリカするわけだけど、writeの可用性を高めるために、フォールバックを含めてwの数だけ書けちゃえばOKってのがwの意味。(だとすると、Bashoのページの例がまさにそうなんだけど、物理3ノードから2ノード落ちてても、残った1ノードが担当するVノードがPrefリストにいくつもあれば、結局その同じ物理ノード(but別のVノード)に複数回コピー取られてOKになってしまうような
    i.e. w=3でも一つノードが生きてればいい。readも同様)

    んでそりゃないだろってことで、プライマリノードのコピー/読み込み成功数を判定基準にしたのが、PW/PRなのかな。ブログに書かれている動作にあってるように思います。

    確認はしてませんので外してたらごめんなさい。やってみようかな。

    • ore より:

      pontaさん

      ありがとうございます!
      僕の方でも確認してみます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Set your Twitter account name in your settings to use the TwitterBar Section.