ceph数据分布

ceph的存储是无主结构,数据分布依赖client来计算,有两个条主要路径。

1、数据到PG

2、PG 到OSD

有两个假设: 第一,pg的数量稳定,可以认为保持不变; 第二, OSD的数量可以增减,OSD的存储空间权重不等;

由于 PG的数量保持不变,由数据来找PGID的环节可以简单处理,对数据的key来取hash值再对pg的总数取模即可唯一确认pgid,pgid=hash(data_key)/pg_num。

难点在于从PG到OSD,如果直接用 hash(pgid)/osd_num的模式,则OSD有增减的时候数据就有无规律的迁移,并且也无法体现OSD的不同权重。

Crush算法就是来解决这个问题的,Crush目的是随机跳出一个OSD,并且要满足权重越大的OSD,挑中的概率越大。

每个OSD有不同的容量,比如是4T还是12T的容量,可以根据每个OSD的容量定义它的权重,以T为单位, 比如4T权重设为4,12T则设为12。

如何将PG映射到不同权重的OSD上面?这里可以直接采用CRUSH里面的Straw抽签算法。

ceph数据分布_第1张图片

核心步骤:

1)计算HASH

draw = CRUSH_HASH( PG_ID, OSD_ID, r ),其中把r当做一个常数,将PG_ID, OSD_ID一起作为输入,得到一个HASH值。

2)增加OSD权重

osd_straw =( draw &0xffff ) * osd_weight

draw &0xffff 得到一个0-65535的数字,再与OSD的权重相乘,以这个作为每个OSD的签长, 权重越大的,数值越大。

3)遍历选取最高的权重

high_draw

Crush所计算出的随机数,是通过HASH得出来,可以保障相同的输入会得出同样的输出结果。

这里只是计算得出了一个OSD,在Ceph集群中是会存在多个副本,如何解决一个PG映射到多个OSD的问题?

将常量r加1, 再去计算一遍,如果和之前的OSD编号不一样, 那么就选取它;如果一样的话,那么再把r+2,再重新计算,直到选出三个不一样的OSD编号。

如果样本容量足够大, 随机数对选中的结果影响逐渐变小, 起决定性的是OSD的权重,OSD的权重越大, 被挑选的概率也就越大。

样本容量足够大,到底是多大? 到底多大才能按照尽可能按照权重来分布,当然是尽量小的样本才好。

样本容量主要由PG和OSD的数量多少来决定,其中最关键的还是OSD数量,如果OSD很少(比如5块盘)也能尽量按照权重分布才好。

PG的数量主要是根据数据预估和OSD的数量来定,有个理论参考数,PG数量 =(OSD数量* 100)/副本数,但是PG数量少影响后面的扩容,太多又占用过多资源,需要有一个平衡。

基于上述考虑,写了一个很简单的程序来验证下数据分布平衡性。

假定OSD数量为5并且权重随机,PG的数量为5000。

结果1:

1.随机生成5个OSDID和对应权重

OSDID=I0N@6nt5pOhjY$g;权重=32.0

OSDID=.nIjl%3zs3aoE7K;权重=16.0

OSDID=S5O9bSS4NMo%qDN;权重=1.0

OSDID=t$lZF91ofuvOKcn;权重=24.0

OSDID=!E2Ia8XE^Jzb5Dz;权重=12.0

2.在pg数量为5000的时候,PG的分布结果:

OSDID=!E2Ia8XE^Jzb5Dz;权重=12.0;拥有的PG数量=625

OSDID=I0N@6nt5pOhjY$g;权重=32.0;拥有的PG数量=2682

OSDID=t$lZF91ofuvOKcn;权重=24.0;拥有的PG数量=1554

OSDID=.nIjl%3zs3aoE7K;权重=16.0;拥有的PG数量=139

结果2:

1.随机生成5个OSDID和对应权重

OSDID=C%EN$UM!e8nZy.R;权重=1.0

OSDID=1iTDBnZeeQ6^Uos;权重=32.0

OSDID=%EMc6a4V5cWi%7D;权重=2.0

OSDID=M7WKDUjLrQaV42D;权重=64.0

OSDID=7OVTO@l$XLE$OV$;权重=8.0

2.在pg数量为5000的时候,PG的分布结果:

OSDID=1iTDBnZeeQ6^Uos;权重=32.0;拥有的PG数量=1201

OSDID=7OVTO@l$XLE$OV$;权重=8.0;拥有的PG数量=18

OSDID=M7WKDUjLrQaV42D;权重=64.0;拥有的PG数量=3781

结果3:

1.随机生成5个OSDID和对应权重

OSDID=TSvabIIG#9IssWW;权重=12.0

OSDID=XglajmN2q3f5qRI;权重=0.8

OSDID=ZEeeX^Wp9tHaxuA;权重=0.5

OSDID=PSiiRAwddyc^ThW;权重=32.0

OSDID=nPI^YbDr0ttVzGa;权重=8.0

2.在pg数量为5000的时候,PG的分布结果:

OSDID=nPI^YbDr0ttVzGa;权重=8.0;拥有的PG数量=319

OSDID=PSiiRAwddyc^ThW;权重=32.0;拥有的PG数量=3816

OSDID=TSvabIIG#9IssWW;权重=12.0;拥有的PG数量=865

package com.test.zhangzk.crush;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;


public class TestCephCrush {
	static String str = "abcdefghijklmnopqrstuvwxyzABCDEDFGHIJKLMNOPQRSTUVWXYZ0123456789.@!#$%^&*";
	static Float[] factories =new Float[] {0.25f,0.5F,0.8f,1f,2f,4f,8f,12f,16f,20f,24f,32f,64f};
	static int pgidCount = 5000;
	static int osdCount = 5;

	public static void main(String[] args) {
		List pgidList = getRandomPgIdList(pgidCount);
		List osdList = getRandomOSDIdList(osdCount);
		HashMap keyCount = new HashMap();
		
		for(int i=0;i osdList = new ArrayList();
		java.util.Random r = new Random(System.currentTimeMillis());
		for( int i=0;i

你可能感兴趣的:(ceph,ceph,存储,crush)