PG如何影响数据分布

引言

有位朋友(下文简称小明)的集群OSD数据分布很不均匀,最多的OSD已经被使用了90%,而最少的才用了40%,这种现象的原因基本上可以确定为PG总数设置少了,再加上经常有朋友会问及到每个Pool的PG数该怎么设置,我这里就说下PG对数据分布的影响。

因为怎么做官网的pg计算器已经讲得很明确了,我主要想介绍下为什么要这么做。

实验环境准备

这里我完全重搭建出了小明的集群环境,需要他提供几个参考值:

  • ceph osd tree : 用于重建CRUSH树,确定OSD权重。
  • ceph df:查看集群数据总数。
  • ceph osd pool ls detail,查看每个pool的PG数。
  • ceph -v: 同样的Ceph版本。

简单概述下小明的集群的状态:三主机,每个主机上13个OSD,每个OSD权重为1.08989,三副本,三个PG数均为512的pool,数据量分别为102GB, 11940GB, 3454GB, 9.2.1的版本的Ceph。

我用手头的三个虚拟机,每个虚拟机建立了13个目录,用来建OSD,配置文件里添加了两个配置osd crush update on start = false, osd journal size = 128,用于建完OSD后,将OSD手动添加至CRUSH中,并保证权重和小明的OSD权重一样,又因为只是试验用,就把journal大小设置很小,主要是盘太多了。

在所有OSD完成prepare+activate正常启动后,创建三个Bucket(host),并将所有的OSD添加至对应的Host下面,形如:ceph osd crush add osd.0 1.08989 host=ceph-1。添加两个pool,并将这三个pool的PG都设置为512,环境准备完毕。给个截图看得清楚点(对的,OSD编号本来就不连续,我是按照原样的顺序重建的):
Alt text

查看数据分布

我从磨磨的博客里找了个统计PG分布的脚本,列出了这个集群的PG分布,如下图:

Alt text

简单说下这个图的意义:

  • pool: 0 1 2:表示pool的编号。
  • osd.0 23 20 18: 表示osd.0上有23个pool 0的PG,20个pool 1的PG,18个pool 2的PG。

这里着重关注下osd.46osd.41上的PG数:
Alt text

osd.41 : 22-17-9
osd.46: 23-33-34

集群三个pool的数据分布为: 102GB, 11940GB, 3454GB

这里我们假定(实际上也是),每个pool里面的PG的数据量是相同的,那么这三个pool的PG数据量平均为:

  • pool 0: 102GB/512 = 0.2GB
  • pool 1: 11940GB/512 = 23.32GB
  • pool 2: 3454GB/512 = 6.75GB

那么这里很快可以计算出这两个OSD上的数据量:

  • osd.41: 22*0.2 + 17*23.32 + 9*6.75 = 461.59GB (实际456G)
  • osd.46: 23*0.2 + 33*23.32 + 34*6.75 = 1003.66GB (实际994G)

这里再给出小明集群磁盘实际使用率,和我这里估算出来的值基本一样,不信可以再找个OSD算算:
Alt text

信息量

整个实验过程,其实包含了很多有用的结论,这里我先罗列下:

  • 只需要提供开篇的几个参考值,搭建出来的集群的PG分布就是完全一样的,因为CRUSH(PG)=>OSD set,CRUSH计算PG分布需要知道OSD的权重,CRUSH的树状结构,pool_id+pg_num,只要这些值一样,计算出的结果也一样,简单点说就是克隆出来一个一模一样的集群,只需要几个参考值。
  • 对于同一个池内的PG,它们的数据量是几乎相等的,这也是有理论依据的,因为HASH(obj) % PG_NUM => PG_ID,这在我的大话CRUSH一文中也有介绍,对于几百万个对象,求余得到的PG_ID是很均匀的,所以PG内的数据量是相等的。
  • 对于不同的pool的PG,分布的数据不一定相等,因为每个pool的数据量不一定相等,比如小明的数据量分布我可以很容易猜测到他使用了openstack+ceph的架构,第一个pool为rbd,没有保存生产数据,二三两个pool的数据比例为11940:3454 = 3.45:1,很明显第二个pool用于保存虚拟机,第三个用于保存镜像。这种近似4:1的数据量的结构一般都是openstack+ceph的架构。而每个PG的数据量是由pool_data/pg_num求得的。
  • 从集群搭建好PG数设置好之后,我们就可以预估某个OSD会在数据量达到一定值的时候被塞满了,我们只需要每个pool的数据总量即可估算,这里我想表达的是,既然这是一个可预见的问题,我们就应该在集群设置之初解决这个问题。

正确设置PG的姿势

首先要定几个规则:

  • 每个OSD上的PG总数应该尽量相等,且在100左右。
  • 每个pool的PG数应该为2的n次方。
  • 每个PG(所有pool)上的数据应该尽量相等。

主要问题在第三点,由上面的数据可以知道,openstack的两个pool的每个PG的平均数据量并不相等:23.32GB和6.75GB,造成不相等的原因是,这两个pool里面保存的数据量总数不相等(通常为3:1~5:1),而他们的PG数却是相等的,所以,如果把他们的PG数设置为4:1的话,总数除以PG数得到的均值应该就基本上相等了。

所以这里,一个非常非常非常重要的结论就是,应该按照集群的所有pool的数据量的比例来设置每个pool的PG数!

而这个比例通常不好估计,Ceph官网给我们提供了一个计算公式,给出了常见的生产配比:

比如openstack结构的给出了8:1的比例,因为volumes池会随业务持续增长,而images池可能在上传完镜像后就不再变化,所以这里的8:1的比例应该是考虑到长远的业务增长造成的volumes池数据不断增长,我们平时看到的3:1->5:1说明业务还有增长空间~~:
Alt text

亦或RGW结构的,对.rgw.buckets数据桶给了较大的PG数:
Alt text

如果我们有30个OSD,跑三副本的话,要保证每个OSD上有100个PG的话,那么一共会有30 (OSD) * 100 (PG/OSD) = 3000 PG ,再除以三副本的3,就是1000个不同的PG,如果使用8:1的结构的话,我们可以分别设为1024128的PG数。 主要方法是让最大的pool向1000靠近,取最接近于2的n次方的值,这里取1024,再加上八分之一的128,最终结果会导致每个OSD上的PG稍微大于100,不过这没有关系,即使到了两百都可以接受。

对于小明的例子,共有69个OSD,每个OSD上有100个PG的话,共有69 * 100 / 3 = 2300个PG,按照八比一来分,大的pool我们取2048,小的取256,一共2304,正好极其接近2300,是一个很理想的值。

再取个比较难分的情况,比如共有100个OSD,那么共有3333个PG,还是八比一,这里我们选择往上取PG值,对于大pool,我们取4096,而不是2048,小pool取512,这样会使得每个OSD平均分到了138个PG,大一点,没有关系的,但是一定不要比100小很多,那样会导致OSD的PG最大最小的比例较大。

主要方法就是求出这个集群总共有多少PG,然后让数据最大的池的PG数向这个数靠近往上取2的n次方,结果大一点没关系,最好每个OSD平均100PG以上,取到了两百也没有关系,就是不能小。

还有个叫rbd的系统默认生成的池,这个池如果没有用到的话,直接删掉就好了。

这时候回过来看下小明的PG分布,剔除rbd池的PG,实际上osd.41上只有17+9=26个PG,而osd.46上却有33+34=67个PG,因为rbd池基本不放数据,所以可以忽视掉对数据分布的影响,就像RGW的PG分布除了数据池很大外其他pool的PG都很小的原因。很明显,数据的分布不均是由于这两个OSD上的PG数比例较大导致的。

解决方法

说了这么多,小明到底应该怎么做呢?首先,要铭记于心的一个结论是:pg_num只能大不能小,很不幸的是,据我所知,小明同学已经把三个pool的pg_num都设置为了1024,如果时间可以倒流的话,我会建议他将volumes池设置为2048,images池设置为512,因为不能再小了,既然已经都设到了1024,那么就再把volumes池的PG设到2048吧,rbd又不想删又不能减小,那就丢那吧,一个空的pool,不论PG多少,都不会对OSD数据分布有影响,起决定作用的是数据最多的那个pool,所以对于volumes池,一定要将PG增大到使得每个OSD的PG(这里的PG可以说是不包含rbd的,仅包含volumes的)平均分布100左右。

还有一个缓解办法:手动调整OSD weight,削峰填谷。对于即将满的OSD,降低它的权重,让它把数据迁移到别的盘上去,但是对于小明这里的情况,需要削的峰太多了,因为100±20的峰和50±20的峰是不一样的,如果是100的话80:120=2:3的比例,如果是50的话就是30:70的比例了,PG的比例会最终导致展现为数据分布的比例。所以,并不是很建议去使用这种缓解方法。

现在,我们删去rbd池,将volumes设到2048,看下PG分布:
Alt text
前面的为volumes池的,最大误差为-20% ~ + 28%, 比之前的-59.6% ~ +52.3%要缩小很多,平均每个OSD上89个volumes池的PG,因为此时两个pool的PG比例为4:1,并且实际数据比例也约为4:1,所以,每个OSD上的PG总数比例就是最终OSD上的数据比例,最小是85个,最大是137个,所以对于一个1.1T的磁盘,最大的存储到1T时,最小的才使用到85/137=0.62T, 不过这要比之前的0.4T要好很多了。对于137这种峰,我们可以削掉。

总结

这篇文章并没有说明在OSD即将满时该怎么处理,而是解释了为什么PG的分布不均会导致OSD的数据分布不均,重点需要明确的观念是,每个pool的PG数量应该根据这个pool实际的保存数据比例来定,最终使得每个OSD的平均PG在一百左右,在构建完集群后,最好检测一下集群的PG分布,提前将几个峰值削去,而不是等到数据真正堆满了再去削,那时候的数据迁移很容易导致集群垮掉,尽量使得每个OSD的PG分布在±20%以下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DL是一个高性能的日志复制服务,提供了持久化、复制以及强一致性的功能,这对于构建可靠的分布式系统都是至关重要的,如复制状态机(replicated-state-machines)、通用的发布/订阅系统、分布式数据库以及分布式队列。DistributedLog会分类维护记录的序列(sequences of records),并将其称为Log(又叫做Log Stream),将记录写入到DL Log的进程称之为Writer,从Log中读取并处理记录的进程称之为Reader。因此,它整体的软件栈如下所示:具体来讲,它包含如下几个组成部分:LogLog是有序的、不可变的日志记录(log record),它的数据结构如下所示:日志记录每条日志记录都是一个字节序列。日志记录会按照序列写入到日志流中,并且会分配一个名为DLSN(分布式序列号,DistributedLog Sequence Number)的唯一序列号。除了DLSN以外,应用程序还可以在构建日志记录的时候设置自己的序列号,应用程序所定义的序列号称为TransactionID(txid)。不管是DLSN还是TransactionID都能用来定位Reader,使其从特定的日志记录开始读取。Log分段(Log Segments)Log会被分解为Log分段,每个分段中包含了其记录的子集。Log分段是分布式的,应该放到Log分段存储中(如BookKeeper)。DistributedLog会基于配置好的策略来轮询每个Log分段,要么是可配置的时间段(如每两个小时),要么是可配置的最大规模(如每128MB)。所以Log的数据将会分为同等大小的Log分段,并且均匀分布到Log分段存储节点上。这样,Log的存储就不会局限于单台服务器的限制,同时,能够在集群中分散读取的流量。Log的数据可以永远保存,直到应用程序显式地将其截断,也可以在一个可配置的时间段内保存。对于构建复制状态机来说,显式截断会非常有用,如分布式数据库。在数据何时能够截断这一点上,它们往往有着严格的控制。基于时间保留Log对于实时分析的场景更为有用,它们只关心一定时间内的数据。命名空间属于同一组织的Log流通常会归类在同一个命名空间(namespace)下,并据此进行管理。DL的命名空间基本上就是用来定位Log流在何处的。应用程序可以在某个命名空间下创建和删除流,也能将某个流截断到给定的序列号上(DLSN或TransactionID均可以)。WriterWriter会将数据写入到它们所选择的Log中。所有的记录都会按照顺序添加到Log之中。序列号是由Writer所负责的,这就意味着对于某个Log,在给定的时间点上,只能有一个激活的Writer。当出现网络分区(network partition),导致两个Writer试图往同一个Log进行写入的时候,DL会保证其正确性,这是通过Log分段存储的屏障(fencing)来实现的。Writer由名为Write Proxy的服务层来提供和管理,Write Proxy用来接受大量客户端的fan-in写入。ReaderReader会从它们所选择的Log中读取记录,这会在一个给定的位置开始。这个给定的位置可以是DLSN,也可以是TransactionID。Reader将会严格按照Log的顺序读取记录。在同一个Log中,不同的Reader可以在不同的起始位置读取记录。与其他的订阅/发布系统不同,DistributedLog并不会记录/管理Reader的位置,它将跟踪的任务留给了应用程序本身,因为不同的应用在跟踪和协调位置上可能会有不同的需求,很难用一种方式就将这些需求全部解决。在应用程序层面,借助各种存储(如ZooKeeper、FileSystem或Key/Value存储)能够很容易地跟踪Reader的位置。Log记录可以缓存在名为Read Proxy的服务层中,从而应对大量Reader的读取。Fan-in与Fan-outDistributedLog的核心支持单Writer、多Reader的语义。服务层构建在DistributedLog Core之上,支持大量的Writer和Reader。服务层包含Write Proxy和Read Proxy,Write Proxy管理Log的Writer,并且在机器宕机时,能够对它们进行故障恢复。它能够从众多来源聚集Writer,允许不必关心Log的所有权(又称为Fan-in)。Read Proxy通过将记录放到缓存中,优化了Reader的读取路径,以应对成百上千的Reader读取同一个Log流的状况。作为一个日志服务,DistributedLog的优势可以总结为:高性能:面对大量的并发日志时,在可持久化的Writer上DL能够提供毫秒级的延迟,同时还能应对上千客户端每秒大量的读取和写入操作。持久化和一致性:消息会持久化到磁盘上,并且以副本的形式存储多份,从而避免丢失。通过严格的顺序,保证Writer和Reader之间的一致性。各种工作负载:DL支持各种负载,包括延迟敏感的在线事务处理(OLTP)应用(如分布式数据库的WAL和基于内存的复制状态机)、实时的流提取和计算以及分析处理。多租户:针对实际的工作负载,DL的设计是I/O隔离的,从而支持多租户的大规模日志。分层架构:DL有一个现代化的分层设计,它将有状态的存储层与无状态的服务提供层进行了分离,能够使存储的扩展独立于CPU和内存,因此支持大规模的写入fan-in和读取fan-out。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值