ceph学习之CRUSH
CRUSH的全称是Controlled Replication Under Scalable Hashing,是ceph数据存储的分布式选择算法,也是ceph存储引擎的核心。在之前的博客里介绍过,ceph的客户端在往集群里读写数据时,动态计算数据的存储位置。这样ceph就无需维护一个叫metadata的东西,从而提高性能。
ceph分布式存储有关键的3R: Replication(数据复制)、Recovery(数据恢复)、Rebalancing(数据均衡)。在组件故障时,ceph默认等待300秒,然后将OSD标记为down和out,并且初始化recovery操作。这个等待时间可以在集群配置文件的mon_osd_down_out_interval参数里设置。在recovery过程中,ceph会重新产生受故障影响的数据。
因为CRUSH会复制数据到不同的磁盘,这些数据副本在recovery时就变得有用。在恢复过程中,CRUSH会尽量移动最小数量的数据,并且产生一个新的集群布局,从而使集群从故障中恢复。
当新的主机或磁盘加入到集群时,CRUSH开始rebalancing操作,它将数据从存在的主机、磁盘迁移到新的主机、磁盘。rebalancing时会尽量利用所有磁盘,以提高集群性能。例如,某个ceph集群包含2000个OSD,现在新加入20个OSD,这样仅1%的数据将被迁移。在迁移中所有存在的磁盘会并行工作,使得迁移工作尽快完成。当然,如果ceph集群在重度使用中,推荐做法是新加入的磁盘设置权重0,并且逐步提高权重,使得数据迁移缓慢发生,以免影响性能。所有的分布式存储在扩容时都建议这样操作,比如我之前写的swift容量管理文章。
在实际中可能经常需要调整集群的布局。默认的CRUSH布局很简单,执行ceph osd tree命令,会看到仅有host和OSD这两种bucket类型在root下面。默认的布局对分区容错很不利,没有rack、row、room这些概念。下面我们增加一种bucket类型:rack(机架)。所有的host(主机)都应位于rack下面。
注:如下文字及图片,都来自《learning ceph》这本书。建议读者有时间详读原著。
(1)执行ceph osd tree得到当前的集群布局:

(2)增加rack:
|
1
2
3
|
$ ceph osd crush add-bucket rack01 rack$ ceph osd crush add-bucket rack02 rack$ ceph osd crush add-bucket rack02 rack |
(3)将host移动到rack下面:
|
1
2
3
|
$ ceph osd crush move ceph-node1 rack=rack01$ ceph osd crush move ceph-node2 rack=rack02$ ceph osd crush move ceph-node3 rack=rack03 |
(4)将rack移动到默认的root下面:
|
1
2
3
|
$ ceph osd crush move rack03 root=default$ ceph osd crush move rack02 root=default$ ceph osd crush move rack01 root=default |
(5)再次运行ceph osd tree命令,会看到新的布局已产生,所有host都位于特定rack下面。按此操作,就完成了对CRUSH布局的调整。

对一个已知对象,可以根据CRUSH算法,查找它的存储结构。比如data这个pool里有一个文件resolv.conf:
|
1
2
|
$ rados -p data lsresolv.conf |
显示它的存储结构:
|
1
2
|
$ ceph osd map data resolv.confosdmap e43 pool 'data' (0) object 'resolv.conf' -> pg 0.9f1f5993 (0.13) -> up ([1,2,0], p1) acting ([1,2,0], p1) |
输出结果说明:
- osdmap e43: 这是osdmap的epoll版本
- pool ‘data’: 这是pool名字
- object ‘resolv.conf’: 这是对象名字
- pg 0.9f1f5993 (0.13): 这是PG号
- up ([1,2,0], p1): 存储该PG的3个OSD都是活跃的,这是一个有序数组,第一个是primary OSD
- acting ([1,2,0], p1): 说明该PG存储在哪3个OSD里,同上也是有序数组
ceph osd map命令只是自己计算一遍CRUSH,它并不确认目标pool里是否真有这个对象,所以随便输入什么文件名,它总是返回成功。
关于对象在ceph里的存储,遵循如下示意图:

首先要存储的大数据(比如rbd设备),被打散成一系列小对象,每个对象会计算出它对应的PG号。取决于replication size的不同,每个PG会分布到多个OSD上。PG的全称是placement groups,它是一个逻辑存储单位,存在的目的是为了更好的管理和定位数以亿计的存储对象。
如何根据对象计算出PG号,以及PG号如何分布到具体的OSD上,这个就是CRUSH算法,如下示意图:

首先,根据对象名和pool里配置的PG数量(这些都已知),运用哈希函数计算出PG号。接下来根据PG号、集群状态、存储规则,运行CRUSH算法,找出具体负责存储的首要和次要OSD。最后客户端从这些OSD上对存储对象进行数据读和写。
在安装ceph的文档里,也提到了如何查看、编辑和更新crushmap。crushmap与ceph的存储架构有关,在实际中可能需要经常调整它。如下先把它dump出来,再反编译成明文进行查看。
|
1
2
3
|
$ ceph osd getcrushmap -o crushmap.originalgot crush map from osdmap epoch 56$ crushtool -d crushmap.original -o crushmap |
然后查看这个文件:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
ceph@ceph:~$ cat crushmap# begin crush maptunable choose_local_tries 0tunable choose_local_fallback_tries 0tunable choose_total_tries 50tunable chooseleaf_descend_once 1tunable straw_calc_version 1# devicesdevice 0 osd.0device 1 osd.1device 2 osd.2# typestype 0 osdtype 1 hosttype 2 chassistype 3 racktype 4 rowtype 5 pdutype 6 podtype 7 roomtype 8 datacentertype 9 regiontype 10 root# bucketshost ceph2 {id -2 # do not change unnecessarily# weight 0.240alg strawhash 0 # rjenkins1item osd.0 weight 0.080item osd.1 weight 0.080item osd.2 weight 0.080}root default {id -1 # do not change unnecessarily# weight 0.240alg strawhash 0 # rjenkins1item ceph2 weight 0.240}# rulesrule replicated_ruleset {ruleset 0type replicatedmin_size 1max_size 10step take defaultstep chooseleaf firstn 0 type osdstep emit}# end crush map |
这个文件包括几节,大概说明下:
- crushmap设备:见上述文件#device后面的内容。这里列举ceph的OSD列表。不管新增还是删除OSD,这个列表会自动更新。通常你无需更改此处,ceph会自动维护。
- crushmap bucket类型:见上述文件#types后面的内容。定义bucket的类型,包括root、datacenter、room、row、rack、host、osd等。默认的bucket类型对大部分ceph集群来说够用了,不过你也可以增加自己的类型。
- crushmap bucket定义:见上述文件#buckets后面的内容。这里定义bucket的层次性架构,也可以定义bucket所使用的算法类型。
- crushmap规则:见上述文件#rules后面的内容。它定义pool里存储的数据应该选择哪个相应的bucket。对较大的集群来说,有多个pool,每个pool有它自己的选择规则。
crushmap的bucket是按层次性分布的,见如下示意图:

crushmap应用的实际场景,举个例子,我们可以定义一个pool名字为SSD,它使用SSD磁盘来提高性能。再定义一个pool名字为SATA,它使用SATA磁盘来获取更好的经济性。不过我手头并没有这样的测试环境,如下配置并非针对我的测试环境进行。假设有3个ceph存储node,每个node上都有独立的osd服务。
首先在crushmap文件里增加如下节:

上述增加2个root bucket,注意id不要冲突。item后面是ceph的node列表,我们假设node1运行SSD硬盘,node2、node3运行SATA硬盘。
再增加2条规则:

- ruleset 3这个规则里,step take sata表示优先选择sata的bucket
- ruleset 4这个规则里,step take ssd表示优先选择ssd的bucket
修改完后,重新编译crushmap并且加载到集群中使之生效。
|
1
2
3
|
$ crushtool -c crushmap -o crushmap.new$ ceph osd setcrushmap -i crushmap.newset crush map |
接下来观察ceph -s是否健康状态OK。如果健康OK,增加2个pool:
|
1
2
3
|
$ ceph osd pool create sata 64 64$ ceph osd pool create ssd 64 64 |
给上述2个新创建的pool分配crush规则:
|
1
2
3
|
$ ceph osd pool set sata crush_ruleset 3$ ceph osd pool set ssd crush_ruleset 4 |
查看规则是否生效:
|
1
|
$ ceph osd dump |egrep -i "ssd|sata" |
现在写往sata pool的目标,将优先存储到SATA设备上。写往ssd pool的目标,将优先存储到SSD设备上。可以用rados命令进行测试:
|
1
2
3
|
$ rados -p ssd put filename file.ssd$ rados -p sata put filename file.sata |
最后使用ceph osd map命令检查它们的存储位置:
|
1
2
3
|
$ ceph osd map ssd file.ssd$ ceph osd map sata file.sata |
本文转自:http://blog.dnsbed.com/archives/1714
ceph学习之CRUSH的更多相关文章
- Ceph学习之路(二)之Ceph的工作原理及流程
一.RADOS的对象寻址 Ceph 存储集群从 Ceph 客户端接收数据——不管是来自 Ceph 块设备. Ceph 对象存储. Ceph 文件系统.还是基于 librados 的自定义实现——并存储 ...
- ceph学习
网络: ceph必须要有公共网络和集群网络: public network:负责客户端交互以及osd与mon之间的通讯 cluster network:负责osd之间的复制,均衡,回填,数据恢复等操作 ...
- 9. Ceph 基础篇 - Crush Maps
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485302&idx=1&sn=00a3a204 ...
- Ceph学习笔记(2)- CRUSH数据分布算法
前言: 分布式存储系统需要让数据均匀的分布在集群中的物理设备上,同时在新设备加入,旧设备退出之后让数据重新达到平衡状态尤为重要.新设备加入后,数据要从不同的老设备中迁移过来.老设备退出后,数据迁移 ...
- Ceph学习之路(一)之ceph初识
一.元数据和元数据管理 (1)元数据 在学习Ceph之前,需要了解元数据的概念.元数据又称为中介数据.中继数据,为描述数据的数据.主要描述数据属性的信息,用来支持如指示存储位置.历史数据.资源查找.文 ...
- Ceph学习笔记(3)- Monitor
Ceph学习笔记(3)- Monitor 前言: Ceph将cluster map与placement rule合并为一张表称为crush map,作为集群表的一部分.由Monitor对集群表的副 ...
- ceph学习之pool
pool是ceph存储数据时的逻辑分区,它起到namespace的作用.其他分布式存储系统,比如Mogilefs.Couchbase.Swift都有pool的概念,只是叫法不同.每个pool包含一定数 ...
- Ceph学习之路(三)Ceph luminous版本部署
1.配置ceph.repo并安装批量管理工具ceph-deploy [root@ceph-node1 ~]# vim /etc/yum.repos.d/ceph.repo [ceph] name=Ce ...
- ceph学习之PG
PG的计算公式: 整个集群PG的计算公式 Total PGs = ((Total_number_of_OSD * ) / max_replication_count) 每个POOL中PG的计算公式: ...
随机推荐
- [IOI2018]组合动作
IOI2018 组合动作 UOJ 首先显然可以两次试出首字母 考虑增量构造 假设首字母为A,且已经试出前i个字母得到的串s 我们考虑press这样一个串s+BB+s+BX+s+BY+s+XA 首先这个 ...
- Symfony 上传图片教程
介绍:我使用的Bundle:"vich/uploader-bundle": "^1.4"; "liip/imagine-bundle": & ...
- php7下 xhprof安装与使用
需要测试下 代码的性能,使用了 xhprof + xhgui 1. 下载xhprof, 这里下载吧 :https://github.com/longxinH/xhprof.git 2, 安装 cd x ...
- python webserver客户端
1.库 suds库,只能做webserver客户端,轻量化,使用方便.安装使用pip. 2.使用 如有webserver情况如下: url:http://10.110.35.41:8980/wsser ...
- 数组中去除重复的对象的简单方法and&&的使用
const arr = [ { name:'tom', age:15 }, { name:'rose', age:17 }, { name:'tom', age:11 }, { name:'rose' ...
- 读:Instance-aware Image and Sentence Matching with Selective Multimodal LSTM
摘要:有效图像和句子匹配取决于如何很好地度量其全局视觉 - 语义相似度.基于观察到这样的全局相似性是由图像(对象)和句子(词)的成对实例之间的多个局部相似性的复合聚集,我们提出了一个实例感知图像和句子 ...
- runtime-分类为什么不生成setter和getter
前言 前几天有人问我一个问题:为什么分类不能自动创建get set方法.老实说,笔者从来没有去思考过这个问题.于是这次通过代码实践跟runtime源码来探究这个问题. 准备工作 为了能减少输出类数据的 ...
- 申请内存的方式(1,malloc/free;2,new/delete)
一.malloc/free的方式 // 4个int 的大小int *p = (int*) malloc(16); for (int i = 0; i < 4; ++i) { p[i] = i; ...
- mac下搭建前端自动化工程
好多年没有接触前端,发现前端行业发生了巨大的变化,很多新鲜术语,比如node.git.grunt.less.sass.预编译.自动化.模块化等等,看得让人晕头转向,不要担心,我会把这之前之后学习成果都 ...
- mysql分区partition
分区后 会产生多个 数据存储文件MYD,MYI ,把内容读取分散到多个文件上,这样减少并发读取,文件锁的概率,提高IO === 水平分区的几种模式:===1. Range(范围) – 这种模式允许DB ...