原文链接:http://www.cnblogs.com/yuxc/archive/2012/07/04/2575536.html
作者:余兴超 @SAE.Sina Web Service Team
请尊重作者辛勤劳动,转载请标注链接和作者
在深入云存储系统Swift核心组件:Ring实现原理剖析和深入云存储系统Swift核心组件:Ring数据结构及构建、重平衡操作两篇博文中,我们详细地分析了Swift中数据的映射机制和具体操作。那么在集群中的每一台存储节点上,Swift是如何实现Account、Container、Object的具体存储呢?本篇旨在分析Storage node与partition,partition与data间的映射关系在实际存储目录中的以何种格式存储,即怎么存,存什么。
在Storage node上运行着Linux系统并使用了XFS文件系统,逻辑上使用一致性哈希算法将固定总数的partition映射到每个Storage node上,每个Data也使用同样的哈希算法映射到Partition上,其层次结构如下图所示:
Figure1:Stoage node hierachy
以我们的一台storage node sws51为例,该device的文件路径挂载到/srv/node/sdc,目录结构如下所示:
root@sws51:/srv/node/sdc# ls
accounts async_pending containers objects quarantined tmp
其中accounts、containers、objects分别是账号、容器、对象的存储目录,async_pending是异步待更新目录,quarantined是隔离目录,tmp是临时目录。
1.objects目录
在objects目录下存放的是各个partition目录,其中每个partition目录是由若干个suffix_path名的目录和一个hashes.pkl文件组成,suffix_path目录下是由object的hash_path名构成的目录,在hash_path目录下存放了关于object的数据和元数据,object存储目录的层次结构如图2所示。
Figure2: Object directory hierachy
hashes.pkl是存放在每个partition中的一个2进制pickle化文件。例如:
root@sws50:/srv/node/sdc/objects/100000# ls
8bd hashes.pkl
In [1]: with open(\'hashes.pkl\', \'rb\') as fp:
...: import pickle
...: hashes = pickle.load(fp)
...:
...:
In [2]: hashes
Out[2]: {\'8bd\': \'9e99c8eedaa3197a63f685dd92a5b4b8\'}
‘8bd’是suffix_dir,而9e99c8eedaa3197a63f685dd92a5b4b8则是该partition下数据的md5哈希值。
Object path生成过程
object的存储路径由object server进程内部称为DiskFile类初始化时产生,过程如下:
1.由文件所属的account、container和object名称产生\'/account/container/object\'格式的字符串,和HASH_PATH_SUFFIX组成新的字符串,调用hash_path函数,生成md5 hash值name_hash。其中HASH_PATH_SUFFIX作为salt来增加安全性,HASH_PATH_SUFFIX值存放在/etc/swift/swift.conf中。
2. 调用storage_directory函数,传入DATADIR, partition, hash_path参数生成DATADIR/partition/name_path[-3:]/name_path格式字符串
3. 连结path/devcie/storage_directory(DATADIR, partition,name_ hash)生成数据存储路径datadir
4. 调用normalize_timestamp函数生成“16位.5位”的时间戳+扩展名的格式生成对象名称
例如,某object的存储路径为:/srv/node/sdc/objects/19892/ab1/136d0ab88371e25e16663fbd2ef42ab1/1320050752.09979.data
其中每个目录分别表示:
Figure3: Object directory represention
Object数据
Object的数据存放在后缀为.data的文件中,它的metadata存放在以后缀为.meta的文件中,将被删除的Object以一个0字节后缀为.ts的文件存放。
2.accounts目录
在accounts目录下存放的是各个partition,而每个partition目录是由若干个suffix_path目录组成,suffix_path目录下是由account的hsh名构成的目录,在hsh目录下存放了关于account的sqlite db,account存储目录的层次结构如图4所示。
Figure4: Account directory hierachy
Account path生成过程
account使用AccountController类来生成path,其过程与object类似,唯一的不同之处在于,account的db命名调用hash_path(account)来生成,而不是使用时间戳的形式。例如,某account的db存储路径为:/srv/node/sdc/accounts/20443/ac8/c7a5e0f94b23b79345b6036209f9cac8/ c7a5e0f94b23b79345b6036209f9cac8.db
Figure5: Object directory represention
Account db数据
在account的db文件中,包含了account_stat、container、incoming_sync 、outgoing_sync 4张表。
表account_stat是记录关于account的信息,如名称、创建时间、container数统计等等,其schema如下:
CREATE TABLE account_stat (
account TEXT,
created_at TEXT,
put_timestamp TEXT DEFAULT \'0\',
delete_timestamp TEXT DEFAULT \'0\',
container_count INTEGER,
object_count INTEGER DEFAULT 0,
bytes_used INTEGER DEFAULT 0,
hash TEXT default \'00000000000000000000000000000000\',
id TEXT,
status TEXT DEFAULT \'\',
status_changed_at TEXT DEFAULT \'0\',
metadata TEXT DEFAULT \'\'
);
account表示account名称,created_at表示创建时间,put_timestamp表示put request的时间戳,delete_timestamp表示delete request的时间戳,container_count为countainer的计数,object_count为object的计数,bytes_used表示已使用的字节数,hash表示db文件的hash值,id表示统一标识符,status表示account是否被标记为删除,status_changed_at表示状态修改时间,metadata表示account的元数据。
以test账号为例,该db的表account_stat中存放了以下数据项:
表container记录关于container的信息,其schema如下:
CREATE TABLE container (
ROWID INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
put_timestamp TEXT,
delete_timestamp TEXT,
object_count INTEGER,
bytes_used INTEGER,
deleted INTEGER DEFAULT 0
);
CREATE INDEX ix_container_deleted_name ON
container (deleted, name);
CREATE TRIGGER container_delete AFTER DELETE ON container
BEGIN
UPDATE account_stat
SET container_count = container_count - (1 - old.deleted),
object_count = object_count - old.object_count,
bytes_used = bytes_used - old.bytes_used,
hash = chexor(hash, old.name,
old.put_timestamp || \'-\' ||
old.delete_timestamp || \'-\' ||
old.object_count || \'-\' || old.bytes_used);
END;
CREATE TRIGGER container_insert AFTER INSERT ON container
BEGIN
UPDATE account_stat
SET container_count = container_count + (1 - new.deleted),
object_count = object_count + new.object_count,
bytes_used = bytes_used + new.bytes_used,
hash = chexor(hash, new.name,
new.put_timestamp || \'-\' ||
new.delete_timestamp || \'-\' ||
new.object_count ||
全部评论
请发表评论