现在的位置: 首页 > 综合 > 正文

深入云存储系统Swift存储节点:存储实现分析

2012年02月16日 ⁄ 综合 ⁄ 共 5302字 ⁄ 字号 评论关闭

   原文链接: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 nodepartitionpartitiondata间的映射关系在实际存储目录中的以何种格式存储,即怎么存,存什么。

   在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

 

 

  其中accountscontainersobjects分别是账号、容器、对象的存储目录,async_pending是异步待更新目录,quarantined是隔离目录,tmp是临时目录。

 

1.objects目录

  在objects目录下存放的是各个partition目录,其中每个partition目录是由若干个suffix_path名的目录和一个hashes.pkl文件组成,suffix_path目录下是由objecthash_path名构成的目录,在hash_path目录下存放了关于object的数据和元数据,object存储目录的层次结构如图2所示。

wps_clip_image-16011

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'}

 

8bdsuffix_dir,而9e99c8eedaa3197a63f685dd92a5b4b8则是该partition下数据的md5哈希值。

 

Object path生成过程

object的存储路径由object server进程内部称为DiskFile类初始化时产生,过程如下:

1.由文件所属的accountcontainerobject名称产生'/account/container/object'格式的字符串,和HASH_PATH_SUFFIX组成新的字符串,调用hash_path函数,生成md5 hashname_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

  其中每个目录分别表示:

 

 

wps_clip_image-23876

Figure3: Object directory represention

 

Object数据

Object的数据存放在后缀为.data的文件中,它的metadata存放在以后缀为.meta的文件中,将被删除的Object以一个0字节后缀为.ts的文件存放。

 

2.accounts目录

accounts目录下存放的是各个partition,而每个partition目录是由若干个suffix_path目录组成,suffix_path目录下是由accounthsh名构成的目录,在hsh目录下存放了关于accountsqlite dbaccount存储目录的层次结构如图4所示。

wps_clip_image-24231

Figure4: Account directory hierachy

 

Account path生成过程

  account使用AccountController类来生成path,其过程与object类似,唯一的不同之处在于,accountdb命名调用hash_path(account)来生成,而不是使用时间戳的形式。例如,某accountdb存储路径为:/srv/node/sdc/accounts/20443/ac8/c7a5e0f94b23b79345b6036209f9cac8/ c7a5e0f94b23b79345b6036209f9cac8.db

 

wps_clip_image-9097

   Figure5: Object directory represention

Account db数据

 

  在accountdb文件中,包含了account_statcontainerincoming_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_countcountainer的计数,object_countobject的计数,bytes_used表示已使用的字节数,hash表示db文件的hash值,id表示统一标识符,status表示account是否被标记为删除,status_changed_at表示状态修改时间,metadata表示account的元数据。

test账号为例,该db的表account_stat中存放了以下数据项:

 

wps_clip_image-5299

 

  表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 || '-' || new.bytes_used);
            END;
CREATE TRIGGER container_update BEFORE UPDATE ON container
            BEGIN
                SELECT RAISE(FAIL, 'UPDATE not allowed; DELETE and INSERT');
            END;

  其中ROWID字段表示自增的主键,name字段表示container的名称,put_timestampdelete_timestamp分别表示containerputdelete的时间戳,object_count表示container内的object数, 

抱歉!评论已关闭.