Flink RocksDB状态后端优化总结

截至当前,Flink 作业的状态后端仍然只有 Memory、FileSystem 和 RocksDB 三种可选,且 RocksDB 是状态数据量较大(GB 到 TB 级别)时的唯一选择。RocksDB 的性能发挥非常仰赖调优,如果全部采用默认配置,读写性能有可能会很差。

但是,RocksDB 的配置也是极为复杂的,可调整的参数多达百个,没有放之四海而皆准的优化方案。如果仅考虑 Flink 状态存储这一方面,我们仍然可以总结出一些相对普适的优化思路。本文先介绍一些基础知识,再列举方法。

Note:本文的内容是基于我们在线上运行的 Flink 1.9 版本实践得出的。在1.10版本及以后,由于 TaskManager 内存模型重构,RocksDB 内存默认成为了堆外托管内存的一部分,可以免去一些手动调整的麻烦。如果性能仍然不佳,需要干预,则必须将 state.backend.rocksdb.memory.managed 参数设为 false 来禁用 RocksDB 内存托管。

Stae R/W on RocksDB

RocksDB 作为 Flink 状态后端时的读写逻辑与一般情况略有不同,如下图所示。

img

Flink 作业中的每一个注册的状态都对应一个列族(column family),即包含自己独立的 memtable 和 sstable 集合。写操作会先将数据写入活动 memtable,写满之后则会转换为不可变 memtable,并 flush 到磁盘中形成 sstable。读操作则会依次在活动 memtable、不可变 memtable、block cache 和 sstable 中寻找目标数据。另外,sstable 也需要通过 compaction 策略进行合并,最终形成分层的 LSM Tree 存储结构,老生常谈了。

特别地,由于 Flink 在每个检查点周期都会将 RocksDB 的数据快照持久化到文件系统,所以自然也就不需要再写预写日志(WAL)了,可以安全地关闭WAL与fsync。

之前笔者已经详细讲解过 RocksDB compaction 策略,并且提到了读放大、写放大和空间放大的概念,对 RocksDB 的调优本质上就是在这三个因子之间取得平衡。而在 Flink 作业这种注重实时性的场合,则要重点考虑读放大和写放大。

img

Tuning MemTable

memtable 作为 LSM Tree 体系里的读写缓存,对写性能有较大的影响。以下是一些值得注意的参数。为方便对比,下文都会将 RocksDB 的原始参数名与 Flink 配置中的参数名一并列出,用竖线分割。

  • write_buffer_size | state.backend.rocksdb.writebuffer.size 单个 memtable 的大小,默认是64MB。当 memtable 大小达到此阈值时,就会被标记为不可变。一般来讲,适当增大这个参数可以减小写放大带来的影响,但同时会增大 flush 后 L0、L1 层的压力,所以还需要配合修改 compaction 参数,后面再提。

  • max_write_buffer_number | state.backend.rocksdb.writebuffer.count memtable 的最大数量(包含活跃的和不可变),默认是2。当全部 memtable 都写满但是 flush 速度较慢时,就会造成写停顿,所以如果内存充足或者使用的是机械硬盘,建议适当调大这个参数,如4。

  • min_write_buffer_number_to_merge | state.backend.rocksdb.writebuffer.number-to-merge 在 flush 发生之前被合并的 memtable 最小数量,默认是1。举个例子,如果此参数设为2,那么当有至少两个不可变 memtable 时,才有可能触发 flush(亦即如果只有一个不可变 memtable,就会等待)。调大这个值的好处是可以使更多的更改在 flush 前就被合并,降低写放大,但同时又可能增加读放大,因为读取数据时要检查的 memtable 变多了。经测试,该参数设为2或3相对较好。

Tuning Block/Block Cache

block 是 sstable 的基本存储单位。block cache 则扮演读缓存的角色,采用 LRU 算法存储最近使用的 block,对读性能有较大的影响。

  • block_size | state.backend.rocksdb.block.blocksize block 的大小,默认值为4KB。在生产环境中总是会适当调大一些,一般32KB比较合适,对于机械硬盘可以再增大到128~256KB,充分利用其顺序读取能力。但是需要注意,如果 block 大小增大而 block cache 大小不变,那么缓存的 block 数量会减少,无形中会增加读放大。

  • block_cache_size | state.backend.rocksdb.block.cache-size block cache 的大小,默认为8MB。由上文所述的读写流程可知,较大的 block cache 可以有效避免热数据的读请求落到 sstable 上,所以若内存余量充足,建议设置到128MB甚至256MB,读性能会有非常明显的提升。

Tuning Compaction

compaction 在所有基于 LSM Tree 的存储引擎中都是开销最大的操作,弄不好的话会非常容易阻塞读写。建议看官先读读前面那篇关于 RocksDB compaction 策略的文章,获取一些背景知识,这里不再赘述。

  • compaction_style | state.backend.rocksdb.compaction.style compaction 算法,使用默认的 LEVEL(即 leveled compaction)即可,下面的参数也是基于此。

  • target_file_size_base | state.backend.rocksdb.compaction.level.target-file-size-baseL1层单个 sstable 文件的大小阈值,默认值为64MB。每向上提升一级,阈值会乘以因子 target_file_size_multiplier(但默认为1,即每级sstable最大都是相同的)。显然,增大此值可以降低 compaction 的频率,减少写放大,但是也会造成旧数据无法及时清理,从而增加读放大。此参数不太容易调整,一般不建议设为256MB以上。

  • max_bytes_for_level_base | state.backend.rocksdb.compaction.level.max-size-level-base L1层的数据总大小阈值,默认值为256MB。每向上提升一级,阈值会乘以因子 max_bytes_for_level_multiplier(默认值为10)。由于上层的大小阈值都是以它为基础推算出来的,所以要小心调整。建议设为 target_file_size_base 的倍数,且不能太小,例如5~10倍。

  • level_compaction_dynamic_level_bytes | state.backend.rocksdb.compaction.level.use-dynamic-size 这个参数之前讲过。当开启之后,上述阈值的乘法因子会变成除法因子,能够动态调整每层的数据量阈值,使得较多的数据可以落在最高一层,能够减少空间放大,整个 LSM Tree 的结构也会更稳定。对于机械硬盘的环境,强烈建议开启。

Generic Parameters

  • max_open_files | state.backend.rocksdb.files.open 顾名思义,是 RocksDB 实例能够打开的最大文件数,默认为-1,表示不限制。由于sstable的索引和布隆过滤器默认都会驻留内存,并占用文件描述符,所以如果此值太小,索引和布隆过滤器无法正常加载,就会严重拖累读取性能。

  • max_background_compactions/max_background_flushes | state.backend.rocksdb.thread.num 后台负责 flush 和 compaction 的最大并发线程数,默认为1。注意 Flink 将这两个参数合二为一处理(对应 DBOptions.setIncreaseParallelism() 方法),鉴于 flush 和 compaction 都是相对重的操作,如果 CPU 余量比较充足,建议调大,在我们的实践中一般设为4。

除了上述设置参数的方法之外,用户还可以通过实现 ConfigurableRocksDBOptionsFactory 接口,创建 DBOptions 和 ColumnFamilyOptions 实例来传入自定义参数,更加灵活一些。看官可参考 Flink 预先定义好的几个 RocksDB 参数集(位于 PredefinedOptions 枚举中)获取更多信息。

RocksDB使用场景和特性

img

  存储和访问数百PB的数据是一个非常大的挑战,开源的RocksDB就是FaceBook开放的一种嵌入式、持久化存储、KV型且非常适用于fast storage的存储引擎。   传统的数据访问都是RPC,但是这样的话访问速度会很慢,不适用于面向用户的实时访问的场景。随着fast storage的流行,越来越多的应用可以通过在flash中管理数据并快速直接的访问数据。这些应用就需要使用到一种嵌入式的database。   使用嵌入式的database的原因有很多。当数据请求频繁访问内存或者fast storage时,网路延时会增加响应时间,比如:访问数据中心网络耗时可能就耗费50ms,跟访问数据的耗时一样多,甚至更多。这意味着,通过RPC访问数据有可能是本地直接访问耗时的两倍。另外,机器的core数越来越多,storage-IOPS的访问频率也达到了每秒百万次,传统数据库的锁竞争和context 切换会成为提高storage-IOPS的瓶颈。所以需要一种容易扩展和针对未来硬件趋势可以定制化的database,RocksDB就是一种选择。   RocksDB是基于Google的开源key value存储库LevelDB,主要满足以下目标:

1、适用于多cpu场景

  商业服务器一般会有很多cpu核,要开发一个随着CPU 核数吞吐量也随之增大的数据库是很困难的,更别提是线性的递增关系。但是,RocksDB是可以高效地运行在多核服务器上。一个优点是RocksDB提供的语义比传统的DBMS更简单。例如:RocksDB支持MVCC,但是仅限于只读的transaction。另一个优点是数据库在逻辑上分片为read-only path和read-write path。这两种方法可以降低锁竞争,而降低锁竞争是支持高并发负载的前提条件。

2、高校利用storage(更高的IOPS、高效的压缩、更少的写磨损)

  现在的存储设备都可以支持到每秒10w的随机读,如果有10块存储卡的话就可以支持每秒100w的随机读。RocksDB可以在这种快速存储上高效运行且不会成为性能瓶颈。   和实时更新的B-tree相比,RocksDB有更好的压缩和更小的写放大。RocksDB由于压缩更优,所以占用更少的storage;由于更小的写放大,flash 设备可以更持久。

3、弹性架构,支持扩展

  RocksDB支持扩展。比如,我们可以新增一个merge operator,这样就可以使用write-only来替代read-modify-write。然而,read和Write是会增加存储的读写IOPS。在写频繁的负载下,这种措施可以降低IOPS。

4、支持IO-bound、in-memory、write-once

  IO-bound workload是指数据库大小远大于内存且频繁地访问storage。in-memory workload是指数据库数据都在内存中且仍然使用storage来持久化存储DB。write-once workload是指大部分的key都只会写入一次或者insert且没有更新操作。现在RocksDB很好支持IO-bound,要想更好地支持in-memory,需要做一些工作。支持write-once的话,还有很多遗留问题待解决。

  RocksDB不是一个分布式的DB,而是一个高效、高性能、单点的数据库引擎。RocksDB是一个持久化存储keys和values的c++ library。keys 和values可以是任意的字节流,且按照keys有序存储。后台的compaction会消除重复的和已删除的key。RocksDB的data以log-structured merge tree的形式存储。RocksDB支持原子的批量写入操作以及前向和后向遍历。   RocksDB采用“可插拔式”的架构,所以很容易替换其中的组件,允许用户很容易在不同的负载和硬件设备上进行调优。

img

1441593_10151976018697200_1580274673_n.png

  比如,用户可以添加不同的压缩模块(snappy, zlib, bzip, etc),且使用不同模块时不用修改源码。这可用于在不同负载下通过配置使用不同的压缩算法。同理,用户可以在compaction时加载个性化的compaction filter来处理keys,例如,可以实现DB的key的"expire-time"功能。RocksDB有可插拔式的API,所以应用可以设计个性化的数据结构来cache DB的写数据,典型应用就是prefix-hash,其中一部分key使用hash存储,剩下的key存储在B-tree。storage file的实现也可以定制开发,所以用户可以实现自己的storage file格式。   RocksDB支持两种compaction style(level style和universal style)。这两种style可做读放大、写放大、空间放大之间做tradeoff。compaction也支持多线程,所以打的DB可以支持高性能的compaction。   RocksDB也提供在线的增量备份接口,也支持bloom filters,这可以在range-scan时降低IOPS。   RocksDB可以充分挖掘使用flash的IOPS,在随机读、随机写和bulk load时性能优于LevelDB。在随机写和bulk load时,性能优于LevelDB 10倍,在随机读时性能优于LevelDB 30%。   LevelDB是单线程执行compaction,在特定的server workload下表现堪忧,但是RocksDB在IO-bound workload下性能明显优于LevelDB。在测试中发现,LevelDB发生频繁的write-stall,这严重影响了DB的99%延迟,另外也发现,把文件mmap到OS cache会引入读性能瓶颈。测试表明,应用不能充分使用flash的高性能,这是因为数据的带宽瓶颈引起了LevelDB的写放大。通过提高写速率和降低写放大,可以避免很多问题,同时提高RocksDB性能。 RocksDB的典型场景(低延时访问): 1、需要存储用户的查阅历史记录和网站用户的应用 2、需要快速访问数据的垃圾检测应用 3、需要实时scan数据集的图搜索query 4、需要实时请求Hadoop的应用 5、支持大量写和删除操作的消息队列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/280626.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

风速预测(八)VMD-CNN-Transformer预测模型

往期精彩内容: 时序预测:LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 风速预测(一)数据集介绍和预处理-CSDN博客 风速预测(二)基于Pytorch的EMD-LSTM模型-CSDN博客 风速预测&#xff…

Sora后时代文生视频的探索

一、写在前面 按常理,这里应该长篇大论地介绍一下Sora发布对各行业各方面产生的影响。不过,这类文章已经很多了,我们今天主要聊聊那些已经成熟的解决方案、那些已经可以“信手拈来”的成果,并以此为基础,看看Sora发布…

GB28181 —— 5、C++编写GB28181设备端,完成将USB摄像头视频实时转发至GB28181服务并可播放(附源码)

被测试的USB摄像头 效果 源码说明 主要功能模拟设备端,完成注册、注销、心跳等,同时当服务端下发指令播放视频时 设备端实时读取USB摄像头视频并通过OpenCV处理后实时转ps格式后封包rtp进行推送给服务端播放。 源码 /****@remark: pes头的封装,里面的具体数据的填写已经占…

远程传输大文件的软件 远程文件传输

在数字化时代,随着数据量的急剧增长,远程传输大文件变得越来越重要。无论是企业间的合作,还是个人的日常需求,高效、稳定、安全的远程文件传输都是关键。本文将介绍远程传输大文件的相关软件及其特点,帮助读者选择最适…

应急响应-Web2

应急响应-Web2 1.攻击者的IP地址(两个)? 192.168.126.135 192.168.126.129 通过phpstudy查看日志,发现192.168.126.135这个IP一直在404访问 , 并且在日志的最后几条一直在访问system.php ,从这可以推断 …

Simulink|局部遮荫下光伏组件多峰值PSO-MPPT控制

目录 主要内容 1.光伏电池工程数学模型的输出特性程序 2.普通扰动观察法进行MPPT 3.基于粒子群寻优的多峰输出特性 4.PSO_MPPT仿真模型 下载链接 主要内容 在实际的光伏发电系统中,由于环境多变等因素的影响,当局部出现被遮挡情况时光伏阵列…

Beamer模板——基于LaTeX制作学术PPT

Beamer模板——基于LaTeX制作学术PPT 介绍Beamer的基本使用安装和编译用于学术汇报的模板项目代码模板效果图 Beamer的高级特性动态效果分栏布局定理环境 介绍 在学术领域,演示文稿是展示和讨论研究成果的重要方式。传统的PowerPoint虽然方便,但在处理复…

音频和视频标签

音频用audio标签 controls表示控制栏 loop循环播放音频 autoplay自动播放&#xff08;浏览器基于隐私一般不支持&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Com…

k8s为什么删除了pod但是还是没删除掉的问题,deployment在影响

deployment 影响pod删除 一、问题所在二、解决问题 一、问题所在 执行&#xff1a;kubectl get pods --all-namespaces&#xff0c;获取dashboard相关的pod kubectl get pods --all-namespaces | grep dashboardkubectl delete pod dashboard-metrics-scraper-546d6779cb-4x6…

Python 深度学习第二版(GPT 重译)(二)

四、入门神经网络&#xff1a;分类和回归 本章涵盖 您的第一个真实世界机器学习工作流示例 处理矢量数据上的分类问题 处理矢量数据上的连续回归问题 本章旨在帮助您开始使用神经网络解决实际问题。您将巩固从第二章和第三章中获得的知识&#xff0c;并将所学应用于三个新…

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-LSTM雪消融…

51单片机学习笔记8 中断系统及定时器

51单片机学习笔记8 中断系统及定时器 一、中断的概念二、51单片机的中断1. 51单片机的中断源2. 中断的优先级3. 中断结构4. 外部中断解读5. 定时器中断6. 串口中断 三、中断相关寄存器1. IE 中断允许寄存器2. TCON 中断请求标志3. IP 中断优先级 四、中断号五、代码实现按键 &a…

html5cssjs代码 029 CSS计数器

html5&css&js代码 029 CSS计数器 一、代码二、解释 该HTML代码定义了一个网页的结构和样式。在头部&#xff0c;通过CSS样式定义了body和h1-h2元素的样式。body元素的样式包括文本居中、计数器重置、字体颜色和背景颜色。h2元素的样式使用了CSS计数器来自动在标题前添加…

Web框架开发-Django模型层(数据库操作)

一、ORM介绍 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动ORM是“对象-关系-映…

stable diffusion webui ubuntu 安装

1.git clone 下来 GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UIStable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.https://github.com/AUTOMATIC1111/stable-diffus…

RAFT: Adapting Language Model to Domain Specific RAG

预备知识 RAG介绍一文搞懂大模型RAG应用&#xff08;附实践案例&#xff09; - 知乎 (zhihu.com) RAG的核心理解为“检索生成” 检索&#xff1a;者主要是利用向量数据库的高效存储和检索能力&#xff0c;召回目标知识&#xff1b; 生成&#xff1a;利用大模型和Prompt工程…

Redis的分片机制

Redis的分片机制 Redis是一个开源的内存数据结构存储系统&#xff0c;它支持键值对的存储方式。Redis的分片机制允许将数据在多个节点上进行分布式存储和处理&#xff0c;从而提高系统的性能和可扩展性。 Redis的分片机制是通过一致性哈希算法实现的。一致性哈希算法将所有的ke…

解决在命令行中输入py有效,输入python无效,输入python会跳转到microsoft store的问题| Bug

目录 如果你已经尝试过将python添加到系统变量在系统变量里把你自己的路径放到应用商店的路径之前删除windowsapps下的python.exe文件 如果你还未将python添加到系统变量没有python安装包且没有配置系统变量 如果你已经尝试过将python添加到系统变量 打开 运行&#xff0c;输入…

Idea 不能创建JDK1.8的spring boot项目

由于https://start.springboot.io/ 不支持JDK1.8&#xff0c;那么我们需要换idea的springboot创建源&#xff0c;需要换成 https://start.aliyun.com&#xff0c;这也是网上大部分教程说的&#xff0c;但是我这边会报这样的错误&#xff1a; Initialization failed for https:…

【C语言】结构体内存对齐问题

1.结构体内存对齐 我们已经基本掌握了结构体的使用了。那我们现在必须得知道结构体在内存中是如何存储的&#xff1f;内存是如何分配的&#xff1f;所以我们得知道如何计算结构体的大小&#xff1f;这就引出了我们今天所要探讨的内容&#xff1a;结构体内存对齐。 1.1 对齐规…