对Flink Rocksdb Statebackend优化的进一步思考

举报
Wei~~~ 发表于 2020/09/07 10:33:43 2020/09/07
【摘要】 Flink目前支持3种Statebackend:Memory,Filesystem,Rocksdb。其中,最适合生产环境使用的,就是Rocksdb。因此,RocksdbStatebackend性能调优也是Flink流作业在生产中进行调优的关键环节。

一、            什么是statebackend

状态(State),Flink官方给出的解释是:在工作流中,当算子只关心每一个独立到来的事件并对其进行处理,这被称为无状态的算子;反之,如果算子需要记住多个事件的信息并对它们进行联合处理时,它就是有状态的算子。

状态是需要存储的,比如窗口聚合操作,当你开了一个5分钟的窗口想要进行聚合计算,你需要先把这5分钟内到来的事件相关信息先保存起来,以便于后面的计算。负责存储状态的模块,就叫做状态后端(Statebackend)。Flink目前支持3StatebackendMemoryFilesystemRocksdb。其中,最适合生产环境使用的,就是Rocksdb。因此,RocksdbStatebackend性能调优也是Flink流作业在生产中进行调优的关键环节。

二、            进一步思考的动力

前段时间,看到了一篇关于RocksdbStatebackend调优的博文,里面提到了很多简单有效的手法,我感触很深,并且对文章中遗留的问题进行了深入的思考,即作者没有实现的针对IO负载进行动态选择的策略,是否可以找到答案。

三、            优化方法的总结

在这里我先对文章中的调优方法进行一下简单的总结:

首先,Rocksdb数据存储需要落盘,而在taskmanager中多个slot并发对state进行访问的时候,由于磁盘的IO大小限制,可能导致某些读写状态的操作需要排队等待。

image.png

因此,为了解决这个问题,Flink中,允许对state存储的地址配置多个路径,而每个路径可以挂载不同的磁盘,这样可以分摊单个磁盘的IO压力。

image.png

但是,在Flink中,分配state存储路径的方式是随机的,经常会出现多个并发进行读写状态还是分配到了同一块磁盘上。

image.png

因此,我们可以对Flink中的代码进行一些小改动,将随机分配路径的方式改成轮询。如果同一个节点有多个taskmanager,需要跨进程进行轮询分配的话,可以考虑zookeeper等第三方组件维护一个公用的DistributedAtomicInteger

image.png

以上基本上对Statebackend的调优完成了,我按照这种方式进行了测试,key在随机生成完全打散的情况下,性能大约能够提升20%~50%,还是很可观的:

image.png

单磁盘情况下单并发性能大约11200 ~ 12700

image.png

多磁盘分摊下单并发性能提升至13500 ~ 17000

 

但随之而来还有一个问题,就是实际生产中,key不可能永远都是打散并且平均分配的,经常会出现数据倾斜的问题,这样很有可能造成某些Slot需要频繁访问State,而某些Slot访问频率相对较少,即多个磁盘的IO是不平衡的。那么我们能否做到在每次对State进行访问的时候,根据磁盘的IO负载情况,动态选择IO较小的磁盘呢?

四、            进一步思考

先从整体的宏观系统来考虑,问题可以简化为多个进程需要相互协调,以完成对多个物理磁盘的读写性能最优。而进程与磁盘之间,还夹杂着操作系统。就像上面提到的需要用到第三方zookeeper才能进行多进程协调一样,操作系统能否提供一个管理者的角色,用于将slot的状态访问请求进行均衡地分发到不同的物理磁盘中执行?

答案是肯定的,以linux为例,这个管理者就是逻辑卷管理器(LVM),我们先来了解一下LVM

逻辑卷管理器(LogicalVolumeManager)本质上是一个虚拟设备驱动,是在内核中块设备和物理设备之间添加的一个新的抽象层次,如图所示。它可以将几块磁盘(物理卷,PhysicalVolume)组合起来形成一个存储池或者卷组(VolumeGroup)LVM可以每次从卷组中划分出不同大小的逻辑卷(LogicalVolume)创建新的逻辑设备。底层的原始的磁盘不再由内核直接控制,而由LVM层来控制。对于上层应用来说卷组替代了磁盘块成为数据存储的基本单元。LVM管理着所有物理卷的物理盘区,维持着逻辑盘区和物理盘区之间的映射。LVM逻辑设备向上层应用提供了和物理磁盘相同的功能,如文件系统的创建和数据的访问等。但LVM逻辑设备不受物理约束的限制,逻辑卷不必是连续的空间,它可以跨越许多物理卷,并且可以在任何时候任意的调整大小。相比物理磁盘来说,更易于磁盘空间的管理。

image.png

逻辑卷管理器原理图

 

试想一下,如果LVM对上层进程屏蔽了多磁盘IO负载并负责进行数据的调度分配,那么slot只需要专职进行状态的读写即可,职责专一,功能解耦。

 

那么LVM是否有多磁盘负载均衡管理的能力呢?答案还是肯定的——磁盘条带化(striping)。让我们再来了解一下条带化:

大多数磁盘系统都对访问次数(每秒的 I/O 操作,IOPS)和数据传输率(每秒传输的数据量,TPS)有限制。当达到这些限制时,后面需要访问磁盘的进程就需要等待,这时就是所谓的磁盘冲突。

避免磁盘冲突是优化 I/O 性能的一个重要目标,而 I/O 性能的优化与其他资源(如CPU和内存)的优化有着很大的区别 ,I/O 优化最有效的手段是将 I/O 最大限度的进行平衡。

条带化技术就是一种自动的将 I/O 的负载均衡到多个物理磁盘上的技术,条带化技术就是将一块连续的数据分成很多小部分并把他们分别存储到不同磁盘上去。这就能使多个进程同时访问数据的多个不同部分而不会造成磁盘冲突,而且在需要对这种数据进行顺序访问的时候可以获得最大程度上的 I/O 并行能力,从而获得非常好的性能。

image.png

条带化示意图(图片来自互联网)

 

从概念上来看,条带化已经完全满足了我们的需求,而且对于目前的大多数的操作系统来说,是天然支持的。我在进行条带化配置之后,经过简单的测试,性能大约能够提升50%甚至1x,由于篇幅原因下回再补上测试结果。附上条带化的配置方式:

#1.创建物理卷PV

pvcreate /dev/sd{b,c,d,e}1 

#2.创建逻辑卷组VG

vgcreate vg0 /dev/sd[bc]1 

#3.创建LV并配置条带化

lvcreate -L 1G -n test2 -i 2 -I 64 vg0

 

五、            总结

本文用一句话来总结,就是利用磁盘条带化技术实现FlinkRocksDB进行状态访问的优化。这样做的好处就是:

1. 能够更加充分利用磁盘IO

2. 不需要对Flink进行代码改造

当然,最基本的条带化是不保证可靠性的,如果一块磁盘坏了有可能数据就全丢了。所以条带化技术还有很多可靠性相关的调整以及进一步性能调优方式,大家可以查找相关资料进行深入研究。

 

华为云DLI服务已经实现了条带化优化技术,欢迎体验交流:https://www.huaweicloud.cn/product/dli.html


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。