【4.分布式存储】-ceph

http://docs.ceph.org.cn/archi...
扩展性极强的分布式对象存储(swift python写的),块存储,文件存储(hdfs和hadoop的结合紧密性能竟然更好,NN节点PB,cephEB,java写的)。
特点:

  • 无路由存储CRUSH,造就极高扩展性;自动failover,rebalance等
  • 日志文件系统(原子+顺序批量)缓存分级,原来默认filestore,日志SSD+无内核缓存+数据fs的正常存储。发展中的Bluestore,ROCKSDB+裸设备,全完无内核缓存,rocksdb还可以优化用NVRAM断电不影响的RAM。
  • 三副本或EC
  • 带条化

组件

客户端:{块,对象,文件},计算路由,与监视器认证和取配置
监视器:认证密钥下发,元数据一致性保证,集群自身可用性(paxos),轻量(数据少,OSD集群相互上报,对它依赖少,6s一次,20s*3个判定失效)
存储集群OSDs:上报状态,与副本集通信复制数据一致性,主要计算发现副本(序号靠前是主)
元数据:包含集群状态没有路由看下官网吧

流程

读写过程

与monitor认证,获取集群配置,
计算pgid(hash,提前规定好pgid,不能改了)
发送到osd机器上
osd副本之间同步返回ack(可以配置SSD缓存,分别ACK确认,第一次返回第二次到磁盘后删除)

带条化

CRUSH

File -> object 映射
Object -> PG 映射 hash(oid) & mask -> pgid。Ceph也推荐PG总数应该为OSD总数的数百倍,以保证有足够数量的PG可供映射。2的幂
PG -> OSD 映射

failover、reblance

新OSD,与monitor通信。Monitor将其加入cluster map,并设置为up且out状态,再将最新版本的cluster map发给这个新OSD。
收到monitor发来的cluster map之后,这个新OSD计算出自己所承载的PG,以及和自己承载同一个PG的其他OSD。然后,新OSD将与这些OSD取得联系。如果这个PG目前处于降级状态(即承载该PG的OSD个数少于正常值,如正常应该是3个,此时只有2个或1个。这种情况通常是OSD故障所致),则其他OSD将把这个PG内的所有对象和元数据复制给新OSD。数据复制完成后,新OSD被置为up且in状态。而cluster map内容也将据此更新。这事实上是一个自动化的failure recovery过程。当然,即便没有新的OSD加入,降级的PG也将计算出其他OSD实现failure recovery

如果该PG目前一切正常,则这个新OSD将替换掉现有OSD中的一个(PG内将重新选出Primary OSD),并承担其数据。在数据复制完成后,新OSD被置为up且in状态,而被替换的OSD将退出该PG(但状态通常仍然为up且in,因为还要承载其他PG)。而cluster map内容也将据此更新。这事实上是一个自动化的数据re-balancing过程。

如果一个OSD发现和自己共同承载一个PG的另一个OSD无法联通,则会将这一情况上报monitor。此外,如果一个OSD deamon发现自身工作状态异常,也将把异常情况主动上报给monitor。在上述情况下,monitor将把出现问题的OSD的状态设为down且in。如果超过某一预订时间期限,该OSD仍然无法恢复正常,则其状态将被设置为down且out。反之,如果该OSD能够恢复正常,则其状态会恢复为up且in。在上述这些状态变化发生之后,monitor都将更新cluster map并进行扩散。这事实上是自动化的failure detection过程。

即便由数千个甚至更多OSD组成,cluster map的数据结构大小也并不惊人。同时,cluster map的状态更新并不会频繁发生。即便如此,Ceph依然对cluster map信息的扩散机制进行了优化,以便减轻相关计算和通信压力。

首先,cluster map信息是以增量形式扩散的。如果任意一次通信的双方发现其epoch不一致,则版本更新的一方将把二者所拥有的cluster map的差异发送给另外一方。
其次,cluster map信息是以异步且lazy的形式扩散的。也即,monitor并不会在每一次cluster map版本更新后都将新版本广播至全体OSD,而是在有OSD向自己上报信息时,将更新回复给对方。类似的,各个OSD也是在和其他OSD通信时,将更新发送给版本低于自己的对方。
基于上述机制,Ceph避免了由于cluster map版本更新而引起的广播风暴。这虽然是一种异步且lazy的机制,但根据Sage论文中的结论,对于一个由n个OSD组成的Ceph集群,任何一次版本更新能够在O(log(n))时间复杂度内扩散到集群中的任何一个OSD上。
如果一个client和它要访问的PG内部的各个OSD看到的cluster map状态一致,则访问操作就可以正确进行。而如果这个client或者PG中的某个OSD和其他几方的cluster map不一致,则根据Ceph的机制设计,这几方将首先同步cluster map至最新状态,并进行必要的数据re-balancing操作,然后即可继续正常访问。

数据格式

底层都是对象:ID,二进制数据,metadata(随意定义)

OSD的日志与bluestore

日志

OSD使用日志的原因有两个:

  • 速度: 日志使得 OSD 可以快速地提交小块数据的写入, Ceph 把小片、随机 IO 依次写入日志,这样,后端文件系统就有可能归并写入动作,并最终提升并发承载力。因此,使用 OSD 日志能展现出优秀的突发写性能,实际上数据还没有写入 OSD ,因为文件系统把它们捕捉到了日志
  • 一致性:OSD需要一个能保证原子化复合操作的文件系统接口。 OSD 把一个操作的描述写入日志,并把操作应用到文件系统。这确保了对象(例如归置组元数据)的原子更新。每隔一段时间(由filestore max sync interval 和 filestore min sync interval控制 ), OSD 会停止写入,把日志同步到文件系统,这样允许 OSD 修整日志里的操作并重用空间。若失败, OSD 从上个同步点开始重放日志。日志的原子性表现在,它不使用操作系统的文件缓存(基于内存),避免断电丢数据的问题

bluestore

直接管理裸设备,抛弃了ext4/xfs等本地文件系统,BlockDevice实现在用户态下使用linux aio直接对裸设备进行I/O操作。
Onode是常驻内存的数据结构,持久化的时候会以kv的形式存到rocksdb里。rocksdb本身是基于文件系统的,封装实现了一个小的文件系统BlueFS,在系统启动mount这个文件系统的时候将所有的元数据都加载到内存中,BluesFS的数据和日志文件都通过BlockDevice保存到裸设备上
https://www.sysnote.org/2016/...
使用HDD作为数据盘
使用SSD作为RockDB元数据盘
使用NVRAM作为RockDB WAL
参考资料:
https://blog.gmem.cc/ceph-stu...
https://www.siguadantang.com/...