Swift 存储目录

  在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所示。


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
  其中每个目录分别表示:   

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所示。

Figure4: Account directory hierachy


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


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中存放了以下数据项:


  表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数, bytes_used  表示已使用的空间,deleted表示container是否标记为删除。
账号testaccount表中的数据项如下所示:


    表incoming_sync记录到来的同步数据项,其schema如下:
CREATE TABLE incoming_sync (
                remote_id TEXT UNIQUE,
                sync_point INTEGER,
                updated_at TEXT DEFAULT 0
            );
CREATE TRIGGER incoming_sync_insert AFTER INSERT ON incoming_sync
            BEGIN
                UPDATE incoming_sync
                SET updated_at = STRFTIME('%s''NOW')
                WHERE ROWID = new.ROWID;
            END;
CREATE TRIGGER incoming_sync_update AFTER UPDATE ON incoming_sync
            BEGIN
                UPDATE incoming_sync
                SET updated_at = STRFTIME('%s''NOW')
                WHERE ROWID = new.ROWID;
            END;
      remote_id字段表示远程节点的idsync_point字段表示上一次更新所在的行位置,updated_at字段表示更新时间。
账号test的表incoming_sync中的数据项如下所示:


  表outgoing_sync表示推送出的同步数据项,其schema如下:
CREATE TABLE outgoing_sync (
                remote_id TEXT UNIQUE,
                sync_point INTEGER,
                updated_at TEXT DEFAULT 0
            );
CREATE TRIGGER outgoing_sync_insert AFTER INSERT ON outgoing_sync
            BEGIN
                UPDATE outgoing_sync
                SET updated_at = STRFTIME('%s''NOW')
                WHERE ROWID = new.ROWID;
            END;
CREATE TRIGGER outgoing_sync_update AFTER UPDATE ON outgoing_sync
            BEGIN
                UPDATE outgoing_sync
                SET updated_at = STRFTIME('%s''NOW')
                WHERE ROWID = new.ROWID;
            END;
    remote_id字段表示远程节点的idsync_point字段表示上一次更新所在的行位置,updated_at字段表示更新时间。
账号test的表remote_id中的数据项如下所示:



3.Container目录
  Container目录结构和生成过程与Account类似,Containerdb中共有5张表,其中incoming_syncoutgoing_syncschemaAccount中的相同。其他3张表分别为container_statobjectsqlite_sequence
  表container_stat与表account_stat相似,其区别是container_stat存放的是关于container信息:

CREATE TABLE container_stat (
                account TEXT,
                container TEXT,
                created_at TEXT,
                put_timestamp TEXT DEFAULT '0',
                delete_timestamp TEXT DEFAULT '0',
                object_count INTEGER,
                bytes_used INTEGER,
                reported_put_timestamp TEXT DEFAULT '0',
                reported_delete_timestamp TEXT DEFAULT '0',
                reported_object_count INTEGER DEFAULT 0,
                reported_bytes_used INTEGER DEFAULT 0,
                hash TEXT default '00000000000000000000000000000000',
                id TEXT,
                status TEXT DEFAULT '',
                status_changed_at TEXT DEFAULT '0',
                metadata TEXT DEFAULT '',
                x_container_sync_point1 INTEGER DEFAULT -1,
                x_container_sync_point2 INTEGER DEFAULT -1
            );

  其中account字段表示container所示的accountcontainer字段表示container名称,created_at表示创建时间,put_timestamp表示put request的时间戳,delete_timestamp表示delete request的时间戳,object_count表示object计数,bytes_used表示使用空间,hash表示db文件的哈希值, reported_put_timestamp, reported_delete_timestamp, reported_object_count, reported_bytes_used表示reported的状态信息,id表示统一标识符,status表示container状态,status_changed_at表示更改时间,metadata表示container的元数据,x_container_sync_point1表示同步点1x_container_sync_point2表示同步点2.
      以名称为testcontainer db为例,其中的表container_stat数据项如下:


  表objectschema如下:

CREATE TABLE object (
                ROWID INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT,
                created_at TEXT,
                size INTEGER,
                content_type TEXT,
                etag TEXT,
                deleted INTEGER DEFAULT 0
            );
CREATE INDEX ix_object_deleted_name ON object (deleted, name);
CREATE TRIGGER object_delete AFTER DELETE ON object
            BEGIN
                UPDATE container_stat
                SET object_count = object_count - (1 - old.deleted),
                    bytes_used = bytes_used - old.size,
                    hash = chexor(hash, old.name, old.created_at);
            END;
CREATE TRIGGER object_insert AFTER INSERT ON object
            BEGIN
                UPDATE container_stat
                SET object_count = object_count + (1 - new.deleted),
                    bytes_used = bytes_used + new.size,
                    hash = chexor(hash, new.name, new.created_at);
            END;
CREATE TRIGGER object_update BEFORE UPDATE ON object
            BEGIN
                SELECT RAISE(FAIL, 'UPDATE not allowed; DELETE and INSERT');
            END;


test container db的表object数据项如下所示:



4.tmp目录
    tmp目录作为account/container/object serverpartition目录内写入数据前的临时目录。
例如,在client向服务端上传某一文件,object server调用DiskFile类的mkstemp方法在创建路径为path/device/tmp的目录。在数据上传完成之后,调用put()方法,将数据移动到相应路径。

5.async_pending目录
  本地server在与remote server建立http连接或者发送数据时超时导致更新失败时,将把文件放入async_pending目录。这种情况经常发生在系统故障或者是高负荷的情况下。如果更新失败,本次更新被加入队列,然后由Updater继续处理这些失败的更新工作。例如,假设一个container server处于负荷下,此时一个新的对象被加入到系统。当Proxy成功地响应Client的请求时,这个对象将变为直接可访问的。但是container服务器并没有更新对象列表,本次更新将进入队列等待延后的更新。所以,container列表不可能马上就包含这个新对象。随后Updater使用object_sweep扫描device上的async pendings目录,遍历每一个prefix目录并执行升级。一旦完成升级,则移除pending目录下的文件(实际上,是通过调用renamer函数将文件移动到object相应的目录下)。
  为了验证以上过程,通过执行一个并发上传1000个文件的脚本,观察sws50的async_pending目录下的所发生的变化。async_pending的路径为/srv/node/sdc/async_pending/,在执行脚本前,该目录下为空。脚本执行完毕后,async_pending目录下产生了一些prefix目录,cd到一个prefix为cb9的目录中,观察其中的数据:
root@sws50:/srv/node/sdc/async_pending/cb9# ll
total 24
-rw------- 1 swift swift 324 2011-11-08 10:15 69a5ee25ea7a4a4b08ea47102930fcb9-1320718532.01864
-rw------- 1 swift swift 324 2011-11-08 10:15 69a5ee25ea7a4a4b08ea47102930fcb9-1320718537.04863
-rw------- 1 swift swift 324 2011-11-08 10:15 69a5ee25ea7a4a4b08ea47102930fcb9-1320718543.08122
-rw------- 1 swift swift 324 2011-11-08 10:15 69a5ee25ea7a4a4b08ea47102930fcb9-1320718550.13288
-rw------- 1 swift swift 324 2011-11-08 10:15 69a5ee25ea7a4a4b08ea47102930fcb9-1320718558.18801
-rw------- 1 swift swift 324 2011-11-08 10:16 69a5ee25ea7a4a4b08ea47102930fcb9-1320718567.25494 
文件路径的组成如下图所示,其中数据名称是由hash_path后面紧跟-,后面是以发送container requestheader中包含的时间戳所产生:


Figure6:  async_pendingdirectory represention

2分钟之后,查看该目录下的文件,仅剩下一个文件:
root@sws50:/srv/node/sdc/async_pending/cb9# ll
total 4
-rw------- 1 swift swift 356 2011-11-08 10:18 69a5ee25ea7a4a4b08ea47102930fcb9-1320718567.25494
最后,async_pending目录变为空。

  account和containerdb pending文件并不会独立地存在于async_pending目录下,它们的pending文件会与其db文件在一个目录下存放。例如:
  某containerdb文件为b8e7f40f8c2012d17aca4e0483d391d0.db,其pending文件为b8e7f40f8c2012d17aca4e0483d391d0.db.pending,一起存放在suffix目录1d0下。
  再次执行测试脚本观察1d0目录下的变化,执行前pending文件的大小为0kb,执行过程中,pending的大小慢慢增加到12kb左右,接着又缓慢下降直到0kb。读取此过程某一时刻的pending文件。
其中内容如下所示:
':gAIoVQM3MzVxAVUQMTMyMTE4NjczMy4yNTQ0N3ECSgBwAQBVGGFwcGxpY2F0aW9uL29jdGV0LXN0
\ncmVhbXEDVSBkYmQzZjhmYjQ1ZmQyZjBkZGZmNTA1ODZkNWU0ZGY3ZnEESwB0Lg==\n:gAIoVQM3Mzh
xAVUQMTMyMTE4NjczMy41MjM4MXECTQDcVRhhcHBsaWNhdGlvbi9vY3RldC1zdHJl\nYW1xA1UgOGI3YzR
iZGVlYzNkZGU4ZDI5OWU1Yzk1ZmE1N2ExZWVxBEsAdC4=\n:gAIoVQM3MzlxAVUQMTMyMTE4NjczMy42M
zg0NnECTQCgVRhhcHBsaWNhdGlvbi9vY3RldC1zdHJl\nYW1xA1UgMmQ1ZDlhYjk0MzlkMTNiMmZhODhiZmF
mNTk3NTRkMjZxBEsAdC4=\n:g..........................................AIoVQM3NDdxAVUQMTM
yMTE4NjczNC40MzIxNnECSgBoAQBVGGFwcGxpY2F0aW9uL29jdGV0LXN0\ncmVhbXEDVSBjYTgzNmZhY2Fh
MzY0MGQwNDc4YTU5OGQzZmUzYmRiNHEESwB0Lg==\n:gAIoVQM3NDlxAVUQMTMyMTE4NjczNC42MzA
1NXECTQCUVRhhcHBsaWNhdGlvbi9vY3RldC1zdHJl\nYW1xA1UgY2Y5NWU3MDIxNWEzOTFlNzcwZDBkODB
jZjlhN2Q5OTlxBEsAdC4=\n:gAIoVQM3NTBxAVUQMTMyMTE4NjczNC43NTA2MXECSgAoAQBVGGFwcGxpY2
F0aW9uL29jdGV0LXN0\ncmVhbXEDVSAyYzU4Zjc3ZGIwMGUxMTgxNjZmNjg2Zjc0YzlmZmNjZHEESwB0Lg==\n'

使用:对以上字符串进行分割成list,我们得到第一个非空元素
y[1]'gAIoVQM3MzVxAVUQMTMyMTE4NjczMy4yNTQ0N3ECSgBwAQBVGG
FwcGxpY2F0aW9uL29jdGV0LXN0\ncmVhbXEDVSBkYmQzZjhmYjQ1ZmQyZjBk
ZGZmNTA1ODZkNWU0ZGY3ZnEESwB0Lg==\n'

使用pickle模块对其进行解码pickle.loads(y[1].decode('base64')),获得一个dict类型的数据:
name, timestamp, size, content_type, etag,deleted=
('735',
'1321186733.25447',
94208,
'application/octet-stream',
'dbd3f8fb45fd2f0ddff50586d5e4df7f',
0)
  表示一个名称为735,大小为94208Bmd5哈希值为dbd3f8fb45fd2f0ddff50586d5e4df7f,可访问的字节流文件。此过程由ContainerBroker类的_commit_puts方法完成,随后使用put_object方法把这些数据项放入container dbobject表中,.pending文件中的数据类型与object表中的字段定义一致。
  从accountcontainerdbobject两者的pending文件处理方式中发现其不同之处在于,dbpending文件在更新完其中的一项数据之后,删除pending文件中的相应的数据项,而object的数据在更新完成之后,移动pending文件到目标目录。

 

6.quarantined目录

  Auditor进程会在本地服务器上每隔一段时间就扫面一次磁盘来检测account、container、object的完整性。一旦发现不完整的数据,该文件就会被隔离,该目录就称为quarantined目录。为了限制Auditor消耗过多的系统资源,其默认扫描间隔是30秒,每秒最大的扫描文件数为20,最高速率为10Mb/s。

  obj auditor使用AuditorWorker类的object_audit方法来检查文件的完整性,该方法封装了obj server的DiskFile类,该类有一个_handle_close_quarantine方法,用来检测文件是否需要被隔离,如果发现损坏,则直接将文件移动到隔离目录下。随后replicator从其他replica那拷贝新的文件来替换,最后Server计算文件的hash值是否正确。整个处理流程如下所示:



Figure7: quarantined object处理流程
  为了验证auditor的有效性,做一个简单的测试,在路径为srv/4/node/sdb4/objects/210/82c/003499609ba80372d6

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
翻译:@胡杨(superhy199148@hotmail.com) @胥可(feitongxiaoke@gmail.com) 校对调整: 寒小阳 龙心尘 时间:2016年7月 出处: http://blog.csdn.net/han_xiaoyang/article/details/51932536 http://blog.csdn.net/longxinchen_ml/article/details/51940065 说明:本文为斯坦福大学CS224d课程的中文版内容笔记,已得到斯坦福大学课程@Rich

三分钟部署Laxcus大数据系统 - 2016-07-20 17:07:47

Laxcus是Laxcus大数据实验室历时五年,全体系自主设计研发的国内首套大数据管理系统。能够支撑百万台级计算机节点,提供EB量级存储和计算能力,兼容SQL和关系数据库。 最新的2.x版本已经全面覆盖和集成当前大数据主流技术和功能 ,并投入到国内多个超算项目中使用。Laxcus同时也保持着使用和部署的极简性,所有对计算机略有认识的人都可以很容易掌握它。下面演示在一台Linux计算机上部署Laxcus demo系统的过程。根据我们的测试,这个部署过程大约需要三分钟,或者您熟悉Linux系统 ,也许不需要这

Devstack多节点部署实验 - 2016-07-20 14:07:52

本文为博主翻译文章,转载请注明出处Bob Hou: http://blog.csdn.net/minxihou 这是个在多物理服务器上部署openstack例子: 1 先决条件Linux网络 1.1 最小化安装系统 你需要一个刚安装好的Linux系统。你可以直接下载最小化的Ubuntu版本,devstack会下载安装所有额外的依赖关系。同样也支持网络安装Fedora,Centos/RHEL.安装几个包用于引导程序配置。 apt -get install -y git sudo || yum install
0 说明 0.1 备注 建立文件夹(sparkdir、hadoop、java、scala、spark) 每台机器均有/usr/sparkdir /hadoop /hadoop - 2.7 .2 /java /jdk1 .8 .0 _91 /scala /scala - 2.11 .8 /spark /spark - 1.6 .1 -bin -without -hadoop . tgz 0.2 用户组、用户管理 资源:http://www.cnblogs.com/vincedotnet/p/ 4017574
Ubuntu16.04安装Hadoop2.6+Spark1.6,并安装python开发工具Jupyter notebook,通过pyspark测试一个实例,調通整个Spark+hadoop伪分布式开发环境。 主要内容:配置root用户,配置Hadoop,Spark环境变量,Hadoop伪分布式安装并测试实例,spark安装并通过Jupter notebook进行开发实例,配置Jupter notebook兼容Python2和python3双内核共存开发。 默认已经正确安装了JDK,并设置了JAVA_HOM
摘要 MLlib(机器学习)分两种——监督学习,无监督学习。首先监督学习,类似普贝叶斯这样的分类算法。要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应。显而眼见的是,这种需求另监督学习有很大的局限性,尤其在海量数据处理时。要预先处理数据以满足算法需求得耗费大量资源与时间。此时,可以使用聚类算法这样的无监督学习,相比于分类,聚类不依赖预定义的类和类标号的训练实例。本文将聚类算法拆分开来。深刻理解其思想。 相关知识 相异度计算——聚类,见名之意,便是将数据聚集起来,但是并非是将所有

Kubernetes1.3新特性 - 2016-07-20 14:07:33

本次分析的kubernetes版本号:v1.3.0。 scheduler模块 新增了kube-api-content-type参数,表示scheduler模块发送给api-server的请求类型,默认值是“application/vnd.kubernetes.protobuf”。 新增了hard-pod-affinity-symmetric-weight参数,表示POD调度规则亲和力的权重,取值范围从0到100。 新增了failure-domains参数,这是一个字符串参数,表示POD调度时亲和力参数。在
kafka学习之路(二)——提高 消息发送流程 因为Kafka 内在就是 分布式的 ,一个Kafka 集群通常包括多个代理。 为了均衡负载,将话题分成多个分区 , 每个代理存储一或多个分区 。 多个生产者和消费者能够同时生产和获取消息 。     过程: 1.Producer根据指定的partition方法(round-robin、hash等),将消息发布到指定topic的partition里面 2.kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关
(上图 2016微软全球合作伙伴大会吸引了144个国家的云解决方案商参会 ) ​2016年7月14日,历时三天的微软全球合作伙伴大会WPC 2016在加拿大多伦多落下帷幕,来自全球144个国家的16,000名软件开发商(ISV)、系统集成商(SI)、增值分销商(VAR)以及新一代云服务商(CSP)等汇聚一堂,他们也是全球最活跃、最顶尖的云计算生态代表。 在本次合作伙伴大会上,微软发布了合作伙伴“红宝书”——《当代微软合作伙伴系列:解决方案商如何在云世纪成功》。这本与IDC合作的书,历时4年完成,每年耗资上

Hadoop使用学习笔记(1) - 2016-07-19 18:07:38

Hadoop使用学习笔记 1.Hadoop安装与基本概念 Hadoop发行版本地址 1.1环境配置需求 本文是用的Hadoop版本是最新的2.7.2发行版。 本文分两个机器环境,分别是研发环境和测试环境: 本地环境配置(配置较好,用于压测): 操作系统: LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0