Ceph是一个分布式存储系统,诞生于2004年,最先致力于开发下一代高性能分布式文件系统的项目。随着云计算的发展,ceph乘上了OpenStack的春风,进而成为了开源社区受关注较高的项目之一。
Ceph有如下优点:mysql
Crush算法是ceph的两大创新之一,简单来讲,ceph摒弃了传统的集中式存储元数据寻址的方案,转而使用CRUSH算法完成数据的寻址操做。CRUSH在一致性哈希基础上很好的考虑了容灾域的隔离,可以实现各种负载的副本放置规则,例如跨机房、机架感知等。Crush算法有至关强大的扩展性,理论上支持数千个存储节点。linux
Ceph中的数据副本数量能够由管理员自行定义,并能够经过CRUSH算法指定副本的物理存储位置以分隔故障域,支持数据强一致性; ceph能够忍受多种故障场景并自动尝试并行修复。redis
Ceph不一样于swift,客户端全部的读写操做都要通过代理节点。一旦集群并发量增大时,代理节点很容易成为单点瓶颈。Ceph自己并无主控节点,扩展起来比较容易,而且理论上,它的性能会随着磁盘数量的增长而线性增加。算法
Ceph支持三种调用接口:对象存储
,块存储
,文件系统挂载
。三种方式能够一同使用。在国内一些公司的云环境中,一般会采用ceph做为openstack的惟一后端存储来提高数据转发效率。sql
Ceph的底层是RADOS,RADOS自己也是分布式存储系统,CEPH全部的存储功能都是基于RADOS实现。RADOS采用C++开发,所提供的原生Librados API包括C和C++两种。Ceph的上层应用调用本机上的librados API,再由后者经过socket与RADOS集群中的其余节点通讯并完成各类操做。数据库
RADOS GateWay、RBD其做用是在librados库的基础上提供抽象层次更高、更便于应用或客户端使用的上层接口。其中,RADOS GW是一个提供与Amazon S3和Swift兼容的RESTful API的gateway,以供相应的对象存储应用开发使用。RBD则提供了一个标准的块设备接口,经常使用于在虚拟化的场景下为虚拟机建立volume。目前,Red Hat已经将RBD驱动集成在KVM/QEMU中,以提升虚拟机访问性能。这两种方式目前在云计算中应用的比较多。swift
CEPHFS则提供了POSIX接口,用户可直接经过客户端挂载使用。它是内核态的程序,因此无需调用用户空间的librados库。它经过内核中的net模块来与Rados进行交互。用于集群中全部数据与对象的存储。处理集群数据的复制、恢复、回填、再均衡。并向其余osd守护进程发送心跳,而后向Mon提供一些监控信息。
当Ceph存储集群设定数据有两个副本时(一共存两份),则至少须要两个OSD守护进程即两个OSD节点,集群才能达到active+clean状态。后端
为Ceph文件系统提供元数据计算、缓存与同步。在ceph中,元数据也是存储在osd节点中的,mds相似于元数据的代理缓存服务器。MDS进程并非必须的进程,只有须要使用CEPHFS时,才须要配置MDS节点。缓存
不管使用哪一种存储方式(对象、块、挂载),存储的数据都会被切分红对象(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设置不一样的优化策略,好比副本数、数据清洗次数、数据块及对象大小等。
Ceph的读写操做采用主从模型,客户端要读写数据时,只能向对象所对应的主osd节点发起请求。主节点在接受到写请求时,会同步的向从OSD中写入数据。当全部的OSD节点都写入完成后,主节点才会向客户端报告写入完成的信息。所以保证了主从节点数据的高度一致性。而读取的时候,客户端也只会向主osd节点发起读请求,并不会有相似于数据库中的读写分离的状况出现,这也是出于强一致性的考虑。因为全部写操做都要交给主osd节点来处理,因此在数据量很大时,性能可能会比较慢,为了克服这个问题以及让ceph能支持事物,每一个osd节点都包含了一个journal文件,稍后介绍。
数据流向介绍到这里就告一段落了,如今终于回到正题:osd进程。在ceph中,每个osd进程均可称做是一个osd节点,也就是说,每台存储服务器上可能包含了众多的osd节点,每一个osd节点监听不一样的端口,相似于在同一台服务器上跑多个mysql或redis。每一个osd节点能够设置一个目录做为实际存储区域,也能够是一个分区,一整块硬盘。以下图,当前这台机器上跑了两个osd进程,每一个osd监听4个端口,分别用于接收客户请求、传输数据、发送心跳、同步数据等操做。
如上图所示,osd节点默认监听tcp的6800到6803端口,若是同一台服务器上有多个osd节点,则依次日后排序。
在生产环境中的osd最少可能都有上百个,因此每一个osd都有一个全局的编号,相似osd0,osd1,osd2........序号根据osd诞生的顺序排列,而且是全局惟一的。存储了相同PG的osd节点除了向mon节点发送心跳外,还会互相发送心跳信息以检测pg数据副本是否正常。
默认大小为5G,也就说每建立一个osd节点,还没使用就要被journal占走5G的空间。这个值是能够调整的,具体大小要依osd的总大小而定。
Journal的做用相似于mysql innodb引擎中的事物日志系统。当有突发的大量写入操做时,ceph能够先把一些零散的,随机的IO请求保存到缓存中进行合并,而后再统一贯内核发起IO请求。这样作效率会比较高,可是一旦osd节点崩溃,缓存中的数据就会丢失,因此数据在还未写进硬盘中时,都会记录到journal中,当osd崩溃后从新启动时,会自动尝试从journal恢复因崩溃丢失的缓存数据。所以journal的io是很是密集的,并且因为一个数据要io两次,很大程度上也损耗了硬件的io性能,因此一般在生产环境中,使用ssd来单独存储journal文件以提升ceph读写性能。
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只有在一些特殊状况才会上报本身的信息,日常只会简单的发送心跳。特殊状况包括:一、新的OSD被加入集群;二、某个OSD发现自身或其余OSD发生异常。Mon节点在收到这些上报信息时,则会更新cluster map信息并加以扩散。
cluster map信息是以异步且lazy的形式扩散的。monitor并不会在每一次cluster map版本更新后都将新版本广播至全体OSD,而是在有OSD向本身上报信息时,将更新回复给对方。相似的,各个OSD也是在和其余OSD通讯时,若是发现对方的osd中持有的cluster map版本较低,则把本身更新的版本发送给对方。
Mds是ceph集群中的元数据服务器,而一般它都不是必须的,由于只有在使用cephfs的时候才须要它,而目在云计算中用的更普遍的是另外两种存储方式。
Mds虽然是元数据服务器,可是它不负责存储元数据,元数据也是被切成对象存在各个osd节点中的,以下图:
在建立CEPHFS时,要至少建立两个POOL,一个用于存放数据,另外一个用于存放元数据。Mds只是负责接受用户的元数据查询请求,而后从osd中把数据取出来映射进本身的内存中供客户访问。因此mds其实相似一个代理缓存服务器,替osd分担了用户的访问压力,以下图: