目录
- 1 Ceph概述
- 2 核心组件
- 3 IO流程
- 4 IO顺序性
- 5 PG一致性协议
- 5.1 StateMachine
- 5.2 Failover Overview
- 5.3 PG Peering
- 5.4 Recovery/Backfill
- 6 引擎概述
- 7 FileStore
- 7.1 架构设计
- 7.2 对外接口
- 7.3 日志类型
- 7.4 幂等操作
- 8 BlueStore
- 8.1 架构设计
- 8.2 BlockDevice
- 8.3 磁盘分配器
- 8.4 BlueFS
- 8.5 对象IO
- 9 未来规划
《浅析开源项目之Ceph》地址:浅析开源项目之Ceph - 知乎 --鱼香肉丝没有鱼
1 Ceph概述
Ceph是由学术界(Sage Weil博士论文)在2006年提出的一个开源的分布式存储系统的解决方案,最早致力于下一代高性能分布式文件存储,经过十多年的发展,还提供了块设备、对象存储S3的接口,成为了统一的分布式存储平台,进而成为开源社区存储领域的明星项目,得到了广泛的实际应用。
Ceph是一个可靠的、自治的、可扩展的分布式存储系统,它支持文件存储、块存储、对象存储三种不同类型的存储,满足存储的多样性需求。整体架构如下:
- 接口层:提供客户端访问存储层的的各种接口,支持POSIX文件接口、块设备接口、对象S3接口,以及用户可以自定义自己的接口。
- Librados:提供上层访问RADOS集群的各种库函数接口,libcephfs、librbd、librgw都是Librados的客户端。
- RADOS:可靠的、自治的分布式对象存储,主要包含Monitor、OSD、MDS节点,提供了一个统一的底层分布式存储系统,支持逻辑存储池概念、副本存储和纠删码、自动恢复、自动rebalance、数据一致性校验、分级缓存、基于dmClock的QoS等核心功能。
2 核心组件
- CephFS:Ceph File System,Ceph对外提供的文件系统服务,MDS来保存CephFS的元数据信息,数据写入Rados集群。
- RBD:Rados Block Device,Ceph对外提供的块设备服务,Ceph里称为Image,元数据很少,保存在特定的Rados对象和扩展属性中,数据写入Rados集群。
- RGW:Rados Gateway,Ceph对外提供的对象存储服务,支持S3、Swift协议,元数据保存在特定的Pool里面,数据写入Rados集群。
- Monitor:保存了MONMap、OSDMap、CRUSHMap、MDSMap等各种Map等集群元数据信息。一个Ceph集群通常需要3个Mon节点,通过Paxos协议同步集群元数据。
- OSD:Object Storage Device,负责处理客户端读写请求的守护进程。一个Ceph集群包含多个OSD节点,每块磁盘一个OSD进程,通过基于PGLog的一致性协议来同步数据。
- MDS:Ceph Metadata Server,文件存储的元数据管理进程,CephFS依赖的元数据服务,对外提供POSIX文件接口,不是Rados集群必须的。
- MGR:Ceph Manager,负责跟踪运行时指标以及集群的运行状态,减轻Mon负担,不是Rados集群必须的。
- Message:网络模块,目前支持Epoll、DPDK(剥离了seastar的网络模块,不使用其share-nothing的框架)、RDMA,默认Epoll。
- ObjectStore:存储引擎,目前支持FileStore、BlueStore、KVStore、MemStore,提供类POSIX接口、支持事务,默认BlueStore。
- CRUSH:数据分布算法,秉承着无需查表,算算就好的理念,极大的减轻了元数据负担(但是感觉过于执着减少元数据了,参考意义并不是很大),但同时数据分布不均,不过已有CRUSH优化Paper。
- SCRUB:一致性检查机制,提供scrub(只扫描元数据)、deep_scrub(元数据和数据都扫描)两种方式。
- Pool:抽象的存储池,可以配置不同的故障域也即CRUSH规则,包含多个PG,目前类型支持副本池和纠删池。
- PG:Placement Group,对象的集合,可以更好的分配和管理数据,同一个PG的读写是串行的,一个OSD上一般承载200个PG,目前类型支持副本PG和纠删PG。
- PGLog:PG对应的多个OSD通过基于PGLog的一致性协议来同步数据,仅保存部分操作的oplog,扩缩容、宕机引起的数据迁移过程无需Mon干预,通过PG的Peering、Recovery、Backfill机制来自动处理。
- Object:Ceph-Rados存储集群的基本单元,类似文件系统的文件,包含元数据和数据,支持条带化、稀疏写、随机读写等和文件系统文件差不多的功能,默认4MB。
3 IO流程
此处以RBD块设备为例简要介绍Ceph的IO流程。
- 用户创建一个Pool,并指定PG的数量。
- 创建Pool/Image,挂载RBD设备,映射成一块磁盘。
- 用户写磁盘,将转换为对librbd的调用。
- librbd对用户写入的数据进行切块并调用librados,每个块是一个object,默认4MB。
- librados进行stable_hash算法计算object所属的PG,然后再输入pg_id和CRUSHMap,根据CRUSH算法计算出PG归属的OSD集合。
- librados将object异步发送到Primary PG,Primary PG将请求发送到Secondary PG。
- PG所属的OSD在接收到对应的IO请求之后,调用ObjectStore存储引擎层提供的接口进行IO。
- 最终所有副本都写入完成才返回成功。
Ceph的IO通常都是异步的,所以往往伴随着各种回调,以FileStore为例看下ObjectStore层面的回调:
- on_journal:数据写入到journal,通常通过DirectIO + Libaio的方式,Journal的数据是sync到磁盘上的。
- on_readable:数据写入Journal且写入Pagecache中,返回客户端可读。
- on_commit:Pagecache中的数据sync到磁盘上,返回客户端真正写成功。
4 IO顺序性
分布式系统中通常需要考虑对象读写的顺序性和并发性,如果两个对象没有共享资源,那么就可以并发访问,如果有共享资源就需要加锁操作。对于同一个对象的并发读写来说,通常是通过队列、锁、版本控制等机制来进行并发控制,以免数据错乱,Ceph中对象的并发读写也是通过队列和锁机制来保证的。
PG
Ceph引入PG逻辑概念来对对象进行分组,不同PG之间的对象是可以并发读写的,单个PG之间的对象不能并发读写,也即理论上PG越多并发的对象也越多,但对于系统的负载也高。
ceph 引入PG的意义:https://blog.csdn.net/bandaoyu/article/details/121847874
不同对象的并发控制
落在不同PG的不同对象是可以并发读写的,落在统一PG的不同对象,在OSD处理线程中会对PG加锁,放进PG队列里,一直等到调用queue_transactions把OSD的事务提交到ObjectStore层才释放PG的锁,也即对于同一个PG里的不同对象,是通过PG锁来进行并发控制,不过这个过程中不会涉及到对象的IO,所以不太会影响效率。
同一对象的并发控制
同一对象的并发控制是通过PG锁实现的,但是在使用场景上要分为单客户端、多客户端。
- 单客户端:单客户端对同一个对象的更新操作是串行的,客户端发送更新请求的顺序和服务端收到请求的顺序是一致的。
- 多客户端:多客户端对同一个对象的并发访问类似于NFS的场景,RADOS以及RBD是不能保证的,CephFS理论上应该可以。
所以接下来主要讨论单客户端下同一对象的异步并发更新。
Message层顺序性
- TCP层是通过消息序列号来保证一条连接上消息的顺序性。
- Ceph Message层也是通过全局唯一的tid来保证消息的顺序性。
PG层顺序性
从Message层取到消息进行处理时,OSD处理OP时划分了多个shard,每个shard可以配置多个线程,PG通过哈希的方式映射到不同的shard里面。OSD在处理PG时,从拿到消息就会PG加了写锁,放入到PG的OpSequencer队列,等到把OP请求下发到ObjectStore端才释放写锁。对于同一个对象的并发读写通过对象锁来控制。
对同一个对象进行写操作会加write_lock,对同一个对象的读操作会加read_lock,也就是读写锁,读写是互斥的。写锁从queue_transactions开始