スケールアウトする分散ブロックデバイスのアイディア

DRBDみたいだけどノードを足すとスケールアウトする感じのもの。ローカルのHDDよりリモートのメモリの方が速いという前提に基づく。RDBMSやファイルサーバーのバックエンドとして。
RDBMSをkey-valueストレージでは置き換えられない状況は少なからず存在する。そんな場合にブロックデバイスレベルでスケールアウトさせることで、CPUとネットワークがボトルネックにならない限りまで性能を向上させることを目論む。


共有するデータのサイズは固定長で、TCPのブロックサイズくらいのサイズで分割し、先頭から 0, 1, 2, ... とインデックスを振る。
サーバーノードの数も固定する。(インデックス mod サーバーノードの数)番目のノードにデータを保存し(ストライピング)、完全に均等に分散されるようにする。
(インデックス mod サーバーノードの数)+1 番目 と +2 番目のノードにもデータをレプリケーションする。レプリケーションは数珠つなぎで行い、スループットを稼ぐ。数珠つなぎだと遅延が増えるわけだが、+1番目のノードにコピーした段階でクライアントにレスポンスを返してしまえば遅延は短縮できる。


サーバーノードを増やしたくなったら、ちょっとread/writeを止めて、一斉にデータを移動させる。移動が終わったら再開。しかしちょぃと工夫すればデータの移動中でもread/writeできるようにすることは可能なんじゃないか。


ネットワークの設計ではクライアントは1台しかいないのがポイント。どうせ1台からしかmountできないのだから問題ない(RedHatの方のGFSとかOCFS2はとりあえず脇に)。ほぼC/Sモデルで設計できる。
サーバーは単にクライアントからの要求に応えるだけ。操作はsaveとreadとmove(moveはサーバー追加時用)。saveされていない領域をreadされたら、単に0埋めのデータを返す。
saveはデータ本体と、レプリケーション先のサーバーノードのアドレスを受け取る。自分に書き込みつつ、レプリケーション先にもデータを投げる。
どのサーバーに書き込み、どのサーバーにレプリケーションするかは、すべてクライアントが計算する。
(脇からread-onlyでmountできると用途が広がりそうだけど、誰かがwriteしているファイルシステムを他のマシンがmountするのはread-onlyでも無理が気もする。ファイルシステム的な問題。それをやるならNFSで共有するとか)


クライアントが落ちたとき、クライアントを復旧できないと困る。そこでクライアントからサーバーにフラグを持たせられるようにすると良いのではないか。あなたはアクティブなサーバーで何番目のサーバーですよ、といったフラグをクライアントから書き込む。サーバーはそのフラグの意味を知っている必要は無く、単に保存し、要求に応えて返信すればいいだけ。つまり簡単なkey-valueストレージ機能を持っていればいい。
復旧したクライアントはサーバーの持っているフラグを参照して、ノードリストを復元する。


クライアントはNBDプロトコルのサーバーを実装すればカーネルからブロックデバイスとして認識できる。ATA over Ethernetでもいいかもしれなが、AoEではブロックサイズを変えられなかったような。ブロックサイズを大きくした方がスループットは向上する。


サーバーのストレージの実装は単なるファイルでいい。save要求を受け取ったら、そのままの位置にそのままデータを書けばいい。そうすると自然にスパースファイルになるから、ディスク容量を無駄に消費することはない。穴の領域からreadすると0が帰ってくるのも都合がいい。


以上設計に穴もありそうだけど、実装できそうだし動きそう。


発想としては、ローカルのメモリとローカルのHDDというキャッシュ階層の間にリモートのメモリを追加しているだけに過ぎない。バッテリーバックアップ付きのRAIDカードに巨大なキャッシュを載せてドーピングしたり、SSDを間に挟めば一緒じゃないかとも思う。その方がCPU負荷も低いし。
とりあえずアイディアだけ。