ストレージのコヒーレンス、アトミック処理など

新しいデータと更新前の古いデータが混在してしまい、古いデータを参照して処理をしてしまうことで大きな問題になることもある。ストレージではこのことをデータの整合性や一貫性と呼んでいて、この整合性をシビアに考えるか、いずれは更新されて全部新しくなる、これをEventual Consistencyと言う。これを如何に担保するか?どう考えるか?これは、アプリケーションごとに異なる。

このストレージにおけるデータの一貫性、コヒーレンスについて知見を深めたいと思う。オンプレミス、データセンタ内のストレージ、分散ストレージはもちろん、なによりクラウド上のストレージ(aws S3やAzure BLOBなど)はどのようにデータの一貫性を保持しているのか?について議論を行い、その基本的な考え方からストレージ全般のデータ一貫性についての理解を深められればと思う。

データの整合性

この不整合をいかに減らすか、というのが、ストレージ最大の問題で、例えば、クラウドでは複数のサーバにデータを配置することで信頼性と性能を高めているが、データ更新時の不整合をどう解決するかという課題がある。

これはデータセンターの中と外では事情が異なります。データセンターの中ではネットワークは非常に高速ですが、データセンター間のネットワークは海底ケーブルなどを通るので遅い。ですので、データセンターの中と外で整合性の技術は分けて作られている。

プライマリ-バックアップ方式とROWA方式、そしてQuoram

不整合を起こさないためにデータセンターの中でよく使われている技術は、プライマリ➖バックアップという方式です。データの複製をいくつか作り、その1つをプライマリ、それ以外をバックアップに指定する。データの読み書きは必ずプライマリデータに対して行う。書き込みの場合にはプライマリデータが更新されるので、更新情報を残りのバックアップに伝達する。

単純なプライマリ-バックアップ方式では、マスターが書き換わり、それ以外のバックアップも書き換わるまではデータの読み書きをしない。ブロックすることで整合性を保持する。

この方式では、仮にプライマリデータが壊れてもバックアップがその代わりを務められるので壊れても大丈夫、というのが基本的な考え方である。

もう1つの方法が、アクティブレプリケーションとかRead-Only-Write-All(ROWA)と呼ばれる方式

これはマスターとそれ以外に分けずに、とにかく書き換え情報を、複製を持っている全部のサーバに伝えて更新していきます。単純に聞こえますが結構難しい方式です。

なぜかというと、ブルーとオレンジという2つデータの書き換えがほぼ同時に起きたとき、必ず全部のサーバでブルーを書き換えたら次にオレンジを書き換える、というように書き換えの順番を揃えなければなりません。順番が間違っているとバックアップにならないから。

そのためにアトミックブロードキャストという、複数のサーバに書き換え情報を送ったときに、どのサーバでも書き換えの順番が同じになるという特殊なプロトコルを使います。

でもこの方法はコストが大きいので、コスト極小化する方法がいくつかあり、有名なのがQuorumという方法。HAクラスタなどでは、サーバの排他処理に用いられることでご存じの方もいると思う。

これは全部のサーバでデータを更新するのだけでなく、一部のサーバだけ更新する。その代わりデータを読み出すときには複数のサーバから読み出すことで、負担を下げるという方法。HAクラスタでは、共有ストレージにQuoramデバイスという領域を確保して、プライマリとそれ以外をストレージ側から排他処理を行うという実装である。

さて、話は戻るが、例えば、5台のサーバがデータの複製を持っているときに、3台だけ更新する。読むときに3台で読むと。ただし、書き込むサーバと読み出すサーバの合計が、全体のサーバ台数より大きいというのが条件。こうすると、少なくとも1台のサーバは書き込みと読み出しで重複します。そして書き込みのデータに順番を付けておくことで、最新の書き込み情報を選ぶことができる、という方法。

これはなかなか賢い方法ですが、運用は難しくて、でもメリットがあります。それはサーバが壊れたとき、それも遅延や挙動がおかしいといった中途半端に壊れたときにはそのサーバにアクセスしなくて済むという点。

これがデータセンターの中での話です。数年前までは、整合性よりも性能やスケーラビリティを上げた方がいいんだとNoSQLデータベースなどが注目されていましたが、アプリケーションにとってデータ整合性がないのは扱いにくい。いまはデータセンター内のネットワークも速くなっているので、厳密な整合性を保ってもそこそこの性能がでている。

もう少し言うと、いまのボトルネックはネットワークではなくHDDの性能で、整合性を犠牲にするよりもHDDをSSDにしたほうが効果的。そのときどきで性能向上に適した技術は変わっていく。

データセンター間は分散コミットを用いる

次にデータセンター間の話です。複数のデータセンターにデータを複製しておけば、ユーザーは最寄りのデータセンターにアクセスすることで遅延も少ないですし、自然災害などでデータセンターが壊れたときにもデータを失う危険性が減る。

でもそのためには、世界中にデータセンターでデータの複製を持っていなければならず、データの書き換えに気をつけないとデータセンターごとに違うデータを持っている、ということになってしまう。

整合性を保つ方法として、先ほどアトミックブロードキャストという技術を紹介しましたが、これはデータセンター間では使えません。データセンター間の通信は遅いし、レイテンシも変動するので更新データが各データセンターに届く順番をコントロールするのは難しい。

そこで、データセンターに更新データが届くタイミングと、実際にデータを書き換えるタイミングを分けて考える。

いちばん典型的なのは分散コミット。ある操作をメンバー全員でやるか、やらないか、どちらかにする。よくクラウドに使われているのが2フェーズコミットプロトコルです。これは映画の撮影をするときに監督が「レディ」と言ったらスタッフが「OK」と答えて「アクション」で撮影をするのと同じ、仮にスタッフの誰かが「ノー」といったら撮影しない。

あるデータセンターがそれ以外のデータセンターに「書き込むか?」と聞いて、みんなからOKをもらったら、コーディネート役のデータセンターが「では書き込んで」と言って操作が行われる。

ただ、この2フェーズコミットでは、例えば監督が「レディ」と言った後で突然クビになってしまうと、ほかのスタッフがOKと返事をしたままずっと監督の「アクション」を待っている、という状態が発生します。スタッフは監督がいなくなったのか、それとも自分が「アクション」を聞き逃したのかが分からないままなので。

この解決策の1つはPAXOSと言って、2フェーズコミットにもう1つ「レディ」「オーケー」を足した3フェーズコミットの一種です。

分散トランザクションやもっと高度な方法で、いかにたくさんのコンピュータで性能よく、効率よくデータの整合性を保ちながら書き換えを行うのか、そういうことを突き詰めていくだけでも、テクノロジートレンドも相まって、情報科学の研究テーマとしては面白いと思う。