mogilefsのような分散Webストレージを妄想ちう(メモです)

思うところがあって、シンプルでスケーラブルな分散Webストレージを考え中。

メモなのでまとまってません。ノード周りはmixiのインスパイア


ターゲットしてはファイル数が億単位になっても大丈夫なぐらいを目指す


いくつか機能としては

  • MySQLに分散情報、メタデータを持つ。
  • bucketという単位を持つ。bucketごと削除が可能かも。ジョブキューが必須
  • ファイルは3台(ハードコード)のノードにコピーする
  • ノードは3台一組。壊れたら同じ組のノードからコピーして復旧する
  • ファイルの保存時に、1台のノードでも保存ができなかったら、別の組に変更する。書いてしまった分はジョブキュー経由で削除
  • ファイルのアップロードはwebdavみたいなインターフェイスで

外部のURL構造は、

http://ws.foo.com/{bucket_name}/{filename}

とし、内部的には

http://node:port/{00}/{00}/{00}/{bucket_id}_{filename_id}

とする。

この際、{filename_id}は、tmaesakaのDigest::MurmurHashを使って32bit uintとなる。

1つのbucketにマジ大量のファイルを置かなければ衝突する可能性はそれなり低い。。はず。

{00}/{00}/{00} はfilename_idの下6桁から生成で。


bucket_idはauto_incrementで付加する。


この様な仕組みを持つと、元のファイル名をかなり小さい容量に圧縮ができ、また計算で求められるため、元のファイル名から内部ファイル名への変換テーブルを持たなくて済む。つまりメタデータのDBを小さくできる。


元のファイル名や付加情報は、コンテンツのヘッダに埋め込む

file content = [length(2byte)][{json data}][data..]
json = {
  ct: 'image/jpeg',
  fn: 'original_filename.jpg'
}

JSONでシリアライズして、長さと一緒に保存しちゃう。


ここまでで、MySQLのスキーマを考えてみると

CREATE TABLE nodes (
    id INT UNSINGED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    gid SMALLINT UNSINGED NOT NULL,
    node varchar(64),
    can_read TINYINT UNSIGNED DEFAULT 0,
    is_fresh TINYINT UNSIGNED DEFAULT 0
) ENGINE=InnoDB;

#id, gid, node,              can_read, is_fresh
#1,  1,  '192.168.55.10:80', 1,        1
#2,  1,  '192.168.55.11:80', 1,        1
#3,  1,  '192.168.55.12:80', 1,        1
#4,  2,  '192.168.55.13:80', 1,        1
#5,  2,  '192.168.55.14:80', 1,        1
#6,  2,  '192.168.55.15:80', 1,        1


CREATE TABLE buckets (
    id INT UNSINGED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32) UNIQUE,
    enable TINYINT UNSINGED DEFAULT 1, --# 一時停止
    delete TINYINT UNSINGED DEFAULT 0, --# 完全削除
) ENGINE=InnoDB

#id, name,        enable, delete
#1,  'kazeburo',  1,      1
#2,  'chibiburo', 1,      1
#3,  '_system',   1,      1


CREATE TABLE objects (
    fid INT UNSINGED NOT NULL, --# filename_id, murmurhash(filename)
    bucket_id INT UNSINGED NOT NULL,
    gid SMALLINT UNSINGED NOT NULL,
    PRIMARY KEY(ckey, bucket_id),
    INDEX (bucket_id)
) ENGINE=InnoDB;

#fid,         bucket_id, gid
#1173386060, 1,         1     #http://ws.foo.com/kazeburo/greatphoto.jpg => node 1,2,3
#3157638903, 2,         1     #http://ws.foo.com/chibiburo/myphoto.jpg   =>  node 1,2,3
#1357344895, 1,         2     #http://ws.foo.com/kazeburo/new.jpg   =>  node 4,5,6

な感じ。


objectsテーブルは、1行のデータサイズが10byteと小さいので、億単位のrowを入れてもなんとかなるんじゃないかと思う。


(object テーブルを変更しました 2010/07/30)

created by blog.nomadscafe.jp

コメント

コメントはありません

コメントを投稿

コメントを投稿するにはログインが必要です