Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1882636
  • 博文数量: 1000
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7921
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-20 09:23
个人简介

storage R&D guy.

文章分类

全部博文(1000)

文章存档

2019年(5)

2017年(47)

2016年(38)

2015年(539)

2014年(193)

2013年(178)

分类: 服务器与存储

2015-07-27 14:31:56

 架构


针对的应用环境是海量文件存储,且底层的存储设备是不可靠的,系统的负载和访问随着时间会动态变化。客户端使用的是用户态程序。

 


?  元数据管理

         使用元数据集群管理元数据请求,元数据都集中存放在OSD上,元数据服务器只用了处理元数据请求已经缓存部分元数据信息;mds集群上缓存的元数据信息使用动态子树分割管理。

         进程打开一个文件:1.MDS解析文件名,将其转会为file inode;2.如果文件存在且访问是合法的,则MDS将文件的inode返回给客户端;3.MDS也可以授予客户端一定的权限(指定哪些操作是合法的,用4个字节标明,包括读,缓存读,写,写缓冲区)

         为了避免使用元数据记录文件的布局,对象名仅仅由文件的inode号和条带号组成;对象的副本通过CRUSH函数分配到OSD上。如果多个client读同一个文件,MDS授权他们读取并且缓存文件内容,通过inode号,layout和文件的大小,client能够为包含文件数据的对象命名并且定位到该对象,可以直接从OSD获取该对象。所有不存在的对象或是字节范围被定义为“洞”或者“0”。如果一个客户端要写一个文件,MDS授予它使用缓冲区写的权限,当文件被关闭时客户端的写权限被撤销,同时将新的文件大小提交到MDS,MDS重新定义该文件的对象信息。

         当写操作跨越对象边界时,客户端获取相关对象的排它锁,然后立即提交写操作,释放锁,通过申请锁和异步刷新数据,对象锁可以掩饰大量写的延迟。有的环境对系统性能有很高的要求,此时就会牺牲系统的一致性,从而获取较高的系统响应。ceph提供特殊的open调用,在打开文件时指定O_LAZY参数,允许应用程序对共享写操作降低一致性要求。lazyio _propagate将指定一个范围的字节并将其刷新到对象存储设备上, lazyio_synchronize确保以后读到的数据都是最新的。

         ceph优化readdir操作,readdir只涉及一次MDS交互,在收到readdir请求后,MDS将返回整个目录的信息,当readdir后有stats查看请求,则可以直接从缓存信息中获取,否则将整个目录的信息舍弃。为了将最新的写操作返回,MDS暂停其他的写操作,收集各个修改操作,将最近的修改内容返回给stats请求。

         MDS使用日志更新数据日志记录允许MDS能够快速有效地将更新的元数据信息发送给OSD集群,同时,每个MDS上的日志能够将重复的元数据更新合并。MDS恢复尚未完成,但是日志能够在一个MDS失效后帮助另一个节点恢复失效节点临界区中的信息,有助于恢复系统的状态。

         ceph的动态子树分割:动态地将缓存的元数据信息分布到一组节点上每个MDS统计自己目录下条目的热度,使用一个计数器来统计,当条目被访问时,计数器+1,同时也会影响其祖先节点,为每个MDS提供一个表述负载分布情况的权值树。定期检查MDS的负载,需要时迁移部分合适大小的子树以维持系统的负载均衡。共享存储和名字空间锁保证了内存中数据迁移的正确性,同时对系统一致性影响最小

根据条目的访问频度作为负载,实现热点迁移à没有考虑各个节点的服务能力,网络的状况,是否可靠?

         元数据服务器的负载均衡和热点问题:1.有大量读访问的目录被复制到多个节点上分散负载;2.当某个目录特别大或是有很重的写负载时,它的部分目录将被迁移到其他节点上客户端访问非热点元数据时,可以将请求直接定位到相应的元数据服务器上;当访问的是热点数据时,客户端将被告知元数据在其他metadata server上或是在多个server上。每个mds的响应会更新客户端缓存的权限,同时会更新与处理条目相关的inode以及它的祖先。

ceph的设计架构和实现机制能够保证,在故障发生前后以及故障产生的过程中,系统的性能保持不变。Ceph有两大特点:1. 每个文件的inode元数据结构相对较小,使得能够将inode结构保存在与它相关的目录项dentry中,此外,能够将一个文件的所有硬链接集中存放在一个辅助表(auxiliarytable)中,ceph将每个目录的信息(dentries和内嵌的inodes)集中保存在共享的对象存储池中,这样,通过访问上层目录就能预取inod2. ceph中每个元数据server上维护了一个更新日志,日志的大小可以达到几百M,这样,server能够从所有的更新操作中提取有效的操作,减少随机IO的次数。

inode以表的形式保存在磁盘上指定的区域,通过inodenumber标识各个inode的位置,C-FFSinode集成到目录的directory中,并且将一个目录下的文件集中放置磁盘上。每个目录下的全部元数据内容以一个对象的形式保存,该对象以目录的inode号命名;每个mds上还维护了一个日志信息,该日志记录了所有最近提交当尚未刷新到目录存储对象上的元数据创建,修改操作。mds的日志被分割为多个固定大小的对象,为这些对象分配一组顺序的标号,通常,为了减小更新操作的延迟,MDS为每个日志entry提交一次I/O操作。当负载很重时,日志的更新也将受到存储层的限制,因为日志更新是大量的小写操作,所以,当负载过重时,MDS集合足够的日志更新以保证有一个较大的增量时再将写入日志的数据写回到对象存储器上。将与一个inode对应的dentry成为primarydentry,其他相关的dentry则成为remote dentry。将inode存放在primarydentry附近,当将一个目录从磁盘读入缓存时,通过一个read操作就可以将该目录的inodedentry一同读入缓存。

元数据被划分为多个子树,子树的边界是目录的片段。每个元数据服务器为本地管理的子树维护一份祖先元数据副本。元数据副本:1.使得节点能够维护一个层次相关性;2.当集群负载过重或是部分节点失效时,能够保证系统的可用性。分布式元数据缓存管理需要满足4个条件:(1)所有缓存的元数据必须与它的根节点相关联,如必须缓存所有祖先节点;(2)所有目录片段必须属于一个子树,如root的目录片段包含许多子树,这些子树不需要所有的dentry,但是他必须有root目录片段的副本;(3)持有副本的MDS需要知道副本的原始元数据所在MDS的信息;(4)元数据的持有者必须知道所有该元数据副本所有者的信息


1+2)保证任何一个节点能够完成路径的解析;((2+3)保证当一个MDS访问到本地子树的边界时,能够确定应该向哪个mds转发请求;(4)当元数据销毁后,能够通知持有该副本的MDS将缓存中的该元数据信息设置为过期

负载均衡MDS为每个inode和目录片段分配一个popularity统计文件/目录的热度,使用一个向量保存<readcounter, write counter>;目录片段还需要统计readdir操作的次数以及元数据从对象存储设备中取出的次数和写入的次数;除了记录自身的热度外,目录还需要维护三个热度统计:1.目录下的所有元数据;2.目录下当前节点是authoritative的元数据;3.只在当前所在子树中的元数据;当元数据收到客户端的请求后,相应的元数据的计数器将增加1个热度,而它的祖先元数据也将相应的增加(热度随着层次结构的回溯指数下降)。MDS集群定期发送各自的负载信息,这样每个负载过重的节点能够决定将本地部分负载迁移到负载较轻的节点上;优先考虑将部分子树迁移到它父目录所在的节点上,文件层次热度统计用了决定选取适合大小的子树进行迁移。每个目录有一个小容量的清单,记录了最近访问该目录的客户端信息。当有新的客户端访问到达时,spreadcount的值将会增大,spread用来协助决定是否需要新建元数据副本。迁移包括交换一些初始化信息,然后执行两步提交:“importing”节点将为迁入的元数据信息写入日志,“exporting”节点通过在日志中记录一个Export事件提交迁移,最后importer日志通过记录一个ImportFinsh标识关闭交易;所有用于迁移元数据子树的根节点信息的bystander节点在迁移开始前将收到子树迁移的通知,在迁移完成以后也会收到通知,因此,任何在缓存中失效的信息将被重新发送到子树原始信息所在的旧的server和新的server

Traffic control:对于不热的元数据条目,可以直接访问元数据所在的MDS节点;对于热点元数据,则可以将请求发给其他节点以分散traffic。默认客户端将请求发给任意的MDS节点,MDS返回给client的信息中包含了当前元数据的副本信息,客户端将这些信息缓存在本地,用以以后访问该元数据或是其祖先节点时使用。对于不热的条目,MDS集群通知client将以后的请求直接发送给元数据所在的MDS节点;而对于热点元数据,则通知client将请求发送给副本所在的节点或是所有的节点。

日志:每个mds上记录了一个日志信息,日志按时间顺序记录所有mds上的原子操作。ceph将日志中的顺序事件划分为多个segment,每个segment的开始标志是一个特殊的子树映射事件,该事件表明当前MDS在某个时间点所管理的子树层次。

失效监测:一个活跃的MDS定期向monitor发送交互信息,如果一个MDS在足够长的一段时间内没有向monitor注册,则认为该MDS失效,monitor更改MDS集群的状态并广播给所有节点。如果一个MDS节点没有在与monitor的交互信息中收到反馈,则该节点将使自身无效。一个MDS失效不会导致数据无法访问,因为MDS上的数据保存在不可失存储介质上了,当一个节点失效后,其他节点上的进程将会恢复失效节点上的数据。recovery过程:1.失效节点的相关日志被读入内存;2.处理有争议的子树分配问题和涉及多个MDStransaction3.client重新建立会话并重新保存打开文件的状态;4.接替失效节点的MDS加入到MDS集群的分布式缓存中。resolve阶段,需要确定状态不确定的事件。恢复节点向所有MDS发送一个resolve信息,该信息中包含了当前恢复节点管理的子树、在迁移过程中出现故障的子树;其他正常运行的MDS也要将这些信息发送给正在恢复的MDS;恢复中的MDS根据收到的子树信息重建自己缓存中的子树层次结构。重建分布式缓存和锁状态:恢复节点向所有MDS发送一个rejoin信息,该信息包含了恢复节点所知道的接受节点拥有的元数据副本信息并宣称自己没有管理的恢复文件;原来有效的节点向恢复节点发送信息,告诉恢复节点自己拥有的元数据副本,并且向恢复节点加入锁状态。恢复节点将自己原本不知道的副本信息加入到自己的缓存中。

?  数据管理

  

数据的布局使用CRUSH管理,将数据的管理从逻辑和物理上分为若干个层次结构,在物理结构上:多个OSD构成一个shelf,多个shelves构成一个cabinet,多个cabinets构成一个row。在逻辑上,将一个文件分成若干个对象,每个对象放置到一个PGs上,而每个PGs被保存到多个OSD上,其中一个作为primary,而其余的OSD则作为副本。

         为了避免负载不均衡或者负载不对称,系统采取让新来的数据随机分配的机制,随机选取已经存在数据的一个子样本迁移到新的设备上。ceph首先使用一个简单的hash函数将对象映射到PGs上,PGs的数量由可调的bit mask控制。为每个OSD分配100个左右的PGs,通过管理每个OSD上的备份元数据来均衡OSD的使用负载。使用CRUSH为OSD分配PGs,它有效地将每个PG映射到一个保存了对象副本的有序OSD列表中。CRUSH仅仅通过PGs和OSD机器映射表就可以定位任何的对象。CRUSH的优势:1.不依赖于任何一方计算出对象的位置2.map的更新不频繁,减少元数据的交换。

         客户端将写请求全部发送到一个对象PG所在的第一个有效的OSD上,PG将副本写到其他的备份OSD上。当所有备份OSD将更新写到本地后,将返回初始OSD一个ack,初始节点本地确认更新完成并返回客户端写完成。读操作直接发送给初始节点。

同步写(sync方式))       

  两种活跃度度量标准:1.OSD是否可达;2.是否被CRUSH分配了数据一个不可达的OSD会先被标记为down,在该OSD上的primary工作将暂时移交给它附近的节点;如果该OSD没有尽快恢复,则它被标记为out,将不参与数据的分配,同时选取另一个OSD加入它原来所在的PGs,客户端发送给失效节点的请求将被重新定向到新的primary上。有时候网络的延时也会导致monitor收集到错误的节点状态信息,当集群映射图(map)更新后,相关的OSD获取更新的map,同时通过与组内的OSD内部ping将新的map发送给组内其他OSD。

阅读(837) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~