こんにちはfukuです。
前回は実際にソースコードから内部的なデータノードの管理について解説を行いました。 今回は、前回少し紹介を行なったznodeのステータスについて詳細に説明を行なって行きます。
zxid
znodeのステータスの説明に入る前に、zxidについての説明を行います。ZooKeeperはもともと、複数のサーバにて分散して動作するように設計がされています。 そのため、各サーバが協調して動作するように、さらにはデータノードを定期的に永続化をする際に、データの整合性を保つためにzxid(ZooKeeperトランザクションID)というものがあります。 zxidはスタンドアローンとクラスタとの実行で少し役割の範囲が異なりますが、ここではスタンドアローンでの場合を考えます。 スタンドアローンでは主にデータの整合性を保つためにzxidを利用します。 そのためノードの追加や変更などのデータ更新を行うたびに、シーケンシャルに増加する値としてzxidがあるという認識で大丈夫です。
znodeのステータス
ではここで、znodeを操作することでどのようにステータスが変化するのかを見て行きましょう。
まず/test
ノードを作成し、ステータスを参照します。
[zk: localhost:2181(CONNECTED) 0] create /test "hoge" Created /test [zk: localhost:2181(CONNECTED) 1] get -s /test hoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0x9 mtime = Sat Mar 31 22:27:40 JST 2018 pZxid = 0x9 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 4 numChildren = 0
cZxid
では対象のznodeを作成した時のzxid、ctime
はznodeを作成したシステム時間がそれぞれ記録されます。
上記から/test
ノードを作成した時のzxidは0x16であることがわかります。
次にmZxid
とmtime
は、それぞれznodeが最終更新された時のzxid、システム時間となるので、以下のように実際に更新してみます。
[zk: localhost:2181(CONNECTED) 2] set /test "hogehoge" [zk: localhost:2181(CONNECTED) 3] get -s /test hogehoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0xa mtime = Sat Mar 31 22:28:01 JST 2018 pZxid = 0x9 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 8 numChildren = 0
znodeを更新することでmZxid
とmtime
が変更されていることがわかります。またzxidの値もインクリメントされてセットされていることが確認できます。
続いてpZxid
ですが、こちらは子ノードを最終更新したzxidとなります。またcversion
は子ノードのバージョン番号となっていて、子ノードが変更されるたびにバージョン番号が変更されます。
[zk: localhost:2181(CONNECTED) 4] create /test/child1 "child1" Created /test/child1 [zk: localhost:2181(CONNECTED) 5] get -s /test hogehoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0xa mtime = Sat Mar 31 22:28:01 JST 2018 pZxid = 0xb cversion = 1 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 8 numChildren = 1
注意しなければならないのは、pZxid
やcversion
はあくまで直属の子ノードに対するものであるので、孫にあたるznodeに対してはステータスの変更は起こりません。
[zk: localhost:2181(CONNECTED) 6] create /test/child1/grandchild1 "grandchild1" Created /test/child1/grandchild1 [zk: localhost:2181(CONNECTED) 7] get -s /test hogehoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0xa mtime = Sat Mar 31 22:28:01 JST 2018 pZxid = 0xb cversion = 1 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 8 numChildren = 1
続いてdataVersion
ですがこちらはznodeに格納するデータのバージョンになります。このdataVersionを比較することによって、他のクライアントが対象データを書き換えを行ったかをチェックすることができます。
znodeに対してデータの書き込みを行う際に、バージョンを指定するオプションがあり、指定したバージョンが現在のdataVersion
と一致する時のみ、書き込みを行うことができます。これによって他のクライアントが書き込みを行った場合には、書き込みを避けると行ったことが可能になります。
[zk: localhost:2181(CONNECTED) 8] set -v 10 /test hogehogehoge version No is not valid : /test [zk: localhost:2181(CONNECTED) 9] set -v 1 /test hogehogehoge [zk: localhost:2181(CONNECTED) 10] get -s /test hogehogehoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0x20 mtime = Sat Mar 31 22:56:32 JST 2018 pZxid = 0xb cversion = 1 dataVersion = 2 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 12 numChildren = 1
aclVersion
はデータノードに設定されているアクセス権のバージョンを示す値となります。以下のようにデータノードのACLを変更することでaclVersion
の値が更新されます
[zk: localhost:2181(CONNECTED) 11] setAcl /test world:anyone:crdwa [zk: localhost:2181(CONNECTED) 12] get -s /test hogehogehoge cZxid = 0x9 ctime = Sat Mar 31 22:27:40 JST 2018 mZxid = 0x20 mtime = Sat Mar 31 22:56:32 JST 2018 pZxid = 0xb cversion = 1 dataVersion = 2 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 12 numChildren = 1
ephemeralOwner
はEPHEMERALモードのデータノードに対してセッションIDを格納ために利用されます。これによってZookeeperは特定のクライアントのセッションが切断された時に、対象のセッションIDとEPHEMERALモードのデータノードに格納されているephemeralOwner
を比較して一致すれば、そのデータノードを削除します。
# zkCliの起動ログ。セッションIDが0x1000363a57c0007に設定されている 2018-03-31 22:52:47,599 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1381] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x1000363a57c0007, negotiated timeout = 30000 [zk: localhost:2181(CONNECTED) 0] create -e /ephemeral Created /ephemeral [zk: localhost:2181(CONNECTED) 1] get -s /ephemeral null cZxid = 0x25 ctime = Sat Mar 31 23:14:16 JST 2018 mZxid = 0x25 mtime = Sat Mar 31 23:14:16 JST 2018 pZxid = 0x25 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x1000363a57c0007 dataLength = 0 numChildren = 0
最後にdataLength
とnumChildren
の値ですが、こちらは文字の通りで、データノードに格納されているデータのバイト数と、子ノードの個数をそれぞれ表しています。
おしまいに
今回はデータノードのステータス管理について記述していきました。特にzxidやバージョン管理を行うことで、複数のクライアントがデータノードに関しての操作を行っても協調しながら状態管理が行えるようになります。