无论使用哪种存储方式(对象、块、挂载),存储的数据都会被切分成对象(Objects)。Objects size大小可以由管理员调整,通常为2M或4M。每个对象都会有一个唯一的OID,由ino与ono生成,虽然这些名词看上去很复杂,其实相当简单。ino即是文件的File ID,用于在全局唯一标示每一个文件,而ono则是分片的编号。比如:一个文件FileID为A,它被切成了两个对象,一个对象编号0,另一个编号1,那么这两个文件的oid则为A0与A1。Oid的好处是可以唯一标示每个不同的对象,并且存储了对象与文件的从属关系。由于ceph的所有数据都虚拟成了整齐划一的对象,所以在读写时效率都会比较高。
但是对象并不会直接存储进OSD中,因为对象的size很小,在一个大规模的集群中可能有几百到几千万个对象。这么多对象光是遍历寻址,速度都是很缓慢的;并且如果将对象直接通过某种固定映射的哈希算法映射到osd上,当这个osd损坏时,对象无法自动迁移至其他osd上面(因为映射函数不允许)。为了解决这些问题,ceph引入了归置组的概念,即PG。
PG是一个逻辑概念,我们linux系统中可以直接看到对象,但是无法直接看到PG。它在数据寻址时类似于数据库中的索引:每个对象都会固定映射进一个PG中,所以当我们要寻找一个对象时,只需要先找到对象所属的PG,然后遍历这个PG就可以了,无需遍历所有对象。而且在数据迁移时,也是以PG作为基本单位进行迁移,ceph不会直接操作对象。
对象时如何映射进PG的?还记得OID么?首先使用静态hash函数对OID做hash取出特征码,用特征码与PG的数量去模,得到的序号则是PGID。由于这种设计方式,PG的数量多寡直接决定了数据分布的均匀性,所以合理设置的PG数量可以很好的提升CEPH集群的性能并使数据均匀分布。
最后PG会根据管理员设置的副本数量进行复制,然后通过crush算法存储到不同的OSD节点上(其实是把PG中的所有对象存储到节点上),第一个osd节点即为主节点,其余均为从节点。
上图中更好的诠释了ceph数据流的存储过程,数据无论是从三中接口哪一种写入的,最终都要切分成对象存储到底层的RADOS中。逻辑上通过算法先映射到PG上,最终存储近OSD节点里。图中除了之前介绍过的概念之外多了一个pools的概念
Pool是管理员自定义的命名空间,像其他的命名空间一样,用来隔离对象与PG。我们在调用API存储即使用对象存储时,需要指定对象要存储进哪一个POOL中。除了隔离数据,我们也可以分别对不同的POOL设置不同的优化策略,比如副本数、数据清洗次数、数据块及对象大小等。
下面我们看看osd的读写流程图,体验一下他的强一致性
Ceph的读写操作采用主从模型,客户端要读写数据时,只能向对象所对应的主osd节点发起请求。主节点在接受到写请求时,会同步的向从OSD中写入数据。当所有的OSD节点都写入完成后,主节点才会向客户端报告写入完成的信息。因此保证了主从节点数据的高度一致性。而读取的时候,客户端也只会向主osd节点发起读请求,并不会有类似于数据库中的读写分离的情况出现,这也是出于强一致性的考虑。
在ceph中,每一个osd进程都可称作是一个osd节点,也就是说,每台存储服务器上可能包含了众多的osd节点,每个osd节点监听不同的端口,类似于在同一台服务器上跑多个mysql或redis。每个osd节点可以设置一个目录作为实际存储区域,也可以是一个分区,一整块硬盘。如下图,当前这台机器上跑了两个osd进程,每个osd监听4个端口,分别用于接收客户请求、传输数据、发送心跳、同步数据等操作。
五、monitor节点
Mon节点监控着整个ceph集群的状态信息,监听于tcp的6789端口。每一个ceph集群中至少要有一个Mon节点,官方推荐每个集群至少部署三台。Mon节点中保存了最新的版本集群数据分布图(cluster map)的主副本。客户端在使用时,需要挂载mon节点的6789端口,下载最新的cluster map,通过crush算法获得集群中各osd的IP地址,然后再与osd节点直接建立连接来传输数据。所以对于ceph来说,并不需要有集中式的主节点用于计算与寻址,客户端分摊了这部分工作。而且客户端也可以直接和osd通信,省去了中间代理服务器的额外开销。
Mon节点之间使用Paxos算法来保持各节点cluster map的一致性;各mon节点的功能总体上是一样的,相互间的关系可以被简单理解为主备关系。如果主mon节点损坏,其他mon存活节点超过半数时,集群还可以正常运行。当故障mon节点恢复时,会主动向其他mon节点拉取最新的cluster map。
Mon节点并不会主动轮询各个osd的当前状态,相反,osd只有在一些特殊情况才会上报自己的信息,平常只会简单的发送心跳。特殊情况包括:1、新的OSD被加入集群;2、某个OSD发现自身或其他OSD发生异常。Mon节点在收到这些上报信息时,则会更新cluster map信息并加以扩散。
cluster map信息是以异步且lazy的形式扩散的。monitor并不会在每一次cluster map版本更新后都将新版本广播至全体OSD,而是在有OSD向自己上报信息时,将更新回复给对方。类似的,各个OSD也是在和其他OSD通信时,如果发现对方的osd中持有的cluster map版本较低,则把自己更新的版本发送给对方。
六、MDS
Mds是ceph集群中的元数据服务器,而通常它都不是必须的,因为只有在使用cephfs的时候才需要它,而目在云计算中用的更广泛的是另外两种存储方式。
Mds虽然是元数据服务器,但是它不负责存储元数据,元数据也是被切成对象存在各个osd节点中的,如下图: