我们处于分布式存储产品选型阶段,做了一些POC测试,在压测阶段发现增减节点对I/O的性能影响都比较大。请问社区大神们如何尽量的降低这种影响?是否有好的处理模式。
讨论这个问题之前,我想先分析一下分布式存储增删节点是如何造成性能影响的?跟哪些因素相关?个人认为增加节点和删除节点是两个场景,可以分开来讨论。
1)元数据类型:分布式存储其中一个重要的特征是存储的数据会分布多台服务器上的不同硬盘上,简单来说,需要正确存取这些数据,系统需要知道哪些数据是存放在那台服务器的哪块硬盘上,这部分的信息需要有元数据来管理。而元数据的组织形式主要有两个大流派,元数据表和一致性哈希。
2)元数据表的原理:通过一个表格记录数据的映射信息,增加一个存储对象就多一条记录,元数据表会随数据量增加不断增大,至于增加节点并不会修改或变更现有的元数据信息,也就是说增加节点并不需要进行数据迁移。
3)一致性哈希的原理:为了避免元数据表的数据量不断膨胀的问题,使用一致性哈希算法运算直接得出数据映射信息,而不需要依赖元数据表。一致性哈希算法涉及 2 个重要变量,集群节点数和节点位于哈希环的位置。增加节点意味着变量更改了,会直接影响到数据分布的位置信息,引发额外的数据迁移操作,数据迁移实际上就是数据传输,肯定会影响性能的。
4)数据重平衡:无论元数据表还是一致性哈希都会遇到一个问题,新增节点上并没有数据,没有办法马上负载压力或者平衡容量空间。为了发挥新节点的功能,需要执行数据重平衡,将一部分数据迁移到新加入节点中,这将触发数据迁移。
上面分析了新增节点触发系统性能影响的原因,下面小结如何避免这种影响。
分布式存储系统中,扩容和缩容不可避免会带来数据重平衡的问题,没有好的处理机制,数据的重构确实会对存储系统的IO带来很大影响。我们的联合方案中针对扩容问题,一方面提供了整池扩容和冷池休眠的机制,这样就可以避免因海量数据重构占用大量网络资源,给前端业务访问带来很大压力的问题;另一方面,我们提供了存储池的QoS功能,可以保证数据重构过程以一个较低的速率进行,这样就大大降低了对存储系统IO的影响。
收起这个问题涉及到了存储节点的QoS的问题。QoS应该是存储系统设计之初就要仔细考虑的架构问题。分析了一众主流存储大厂后还是觉得ceph在这方面做得最细致最全面。同时也有些厂商做得比较简陋,只提供了带宽或者IOPS的限速功能。这或许在某些场景中已经够用,但我认为一个完整的QoS方案至少要包括对带宽、IOPS的预留、上限和优先级控制,如果再精细点还可以考虑IO的粒度、延迟、突发、空间局部性、系统内部IO、用户IO、缓存、磁盘等要素。
分布式存储都有很长的IO路径,简单的IOPS限速功能通常在路径的最前端实现。例如OpenStack Cinder默认使用QEMU完成存储块的限速功能,QEMU对存储来说已经属于客户端的角色了。
QoS的本质总结起来就四个字:消此长彼,它并不会提高系统整体处理能力,只是负责资源的合理分配。
对Ceph来说,OSD的ShardedOpWq队列是个不错的选择,因为几乎所有重量级的IO都会经过该队列。这些IO可以划分为两大类,一类是客户端过来的IO,包括文件、对象和块存储;另一类是系统内部活动产生的IO,包括副本复制、Scrub、Recovery和SnapTrim等。
目前Ceph QoS最新提交了两个有关QoS的PR,具体如下:
1)dmClock Update
dmClock算法分为客户端和服务器端,服务器端一般驻留在OSD上,不会有太大变化,主要是客户端的设计,目前社区有三种初步方案:
1,使用mclock作为一种资源调度策略,控制客户端I/O请求和Ceph内部I/O之间的优先次序
2,使用卷或者存储池作为粒度,为其设置一套QOS模板
3,为每个真实的客户端提供一套QOS模板.
2)rbd: implement image qos in tokenbucket algorithm
这个是国内团队提交的一个关于rbd块设备读写镜像时候采用令牌桶算法的一直QOS方式