文章目录

  • 写性能优化
    • CF write buffer size
    • DB write buffer size
  • 读性能优化
    • block cache
    • bloom filter
    • Compression 压缩
  • Compaction优化
  • 通用workload的配置

本文在rocksdb 整个读写链路基础上给出一些简单的调优策略,主要是通过调整一些 参数来满足我们大多数workload的性能需求。

更详细的源代码分析暂不涉及,一部分调优机制的源代码分析之前的部分文章中已经有过描述,需要的话会在文中提及。6.4及以上版本的实现中有超过200个参数,对于大多数使用rocksdb的同学来说实在是负担太重,想要通过分析源代码来明确每一个参数的深层含义以及在不同workload下的其表现最优的值显然是不可能的,所以只需要明确核心链路的可优化点即可。

通过本文,能够清楚 读写性能调优,compaction的核心调优,通用的优化配置。

写性能优化

我们知道rocksdb是基于LSM架构的单机存储引擎,其拥有高效的写吞吐。为了保证一致性,整个写入链路会先写WAL,再写memtale即可返回。其中WAL如果开了sync,则需要走一次I/O ,memtable是一个内存数据结构,通常是跳表实现的,基本属于CPU计算。后续数据在memtable的罗盘则通过异步的flush来进行。

wal的写入无法避免,写入参数上的优化就主要集中在写memtable上了。
rocksdb提供了write buffer size的配置,即单个memtable能够接受的最大写入量,并且提供了可以设置每一个DB/ColumnFamily 的写缓存配置。

CF write buffer size

cf_options.write_buffer_size = 64 << 20; 默认是64M。

可以用来设置以Column Family为单位的缓存大小。设置之前最好预估一下最坏情况下的内存使用量,如果发现内存不够用,那么需要降低这个数值。

DB write buffer size

db_options.write_buffer_size = 64 << 30;默认值是0。
这个配置用来设置整个db 所有column family 共享的write buffer size, 表示整个db的write buffer size达到阈值,会对当前db的所有cf进行flush。

如果需要改变这个值,可以通过如上参数的方式将该值设置为64G。

读性能优化

block cache

block cache 主要是用来缓存解压后的数据。blockcache的大小,社区给的建议是 整个内存有效负载大小的1/3。即如果内存有效负载是240G(240G的used的情况下操作系统仍能正常工作,不需要回收低优先级的进程内存),那么blockcache的大小就设置为80G。

block cache的配置可以通过table_options来进行设置,需要注意的是为了保证所有的column family共用一个blockcache,需要让table_options对象所有的cf_options的table_factory公用。

auto cache = NewLRUCache(128 << 20);  // LRUcacheBlockBasedTableOptions table_options;
table_options.block_cache = cache;auto table_factory = new BlockBasedTableFactory(table_options);
cf_options.table_factory.reset(table_factory);

bloom filter

如果你的系统中有查找相关的操作,建议打开bloom filter这个配置。bloom filter主要是用来过滤sst文件中不存在的key的查找请求,可以在O(1)时间内完成这个操作,而不需要额外的CPU计算和昂贵的I/O操作。

需要注意的是bloom filter能够有效提升点查性能,却无法提升range scan的性能。

通过如下配置来打开bloom filter,并将bloom filter位数设置为10位。

rocksdb::BlockBasedTableOptions table_options;
table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));auto table_factory = new rocksdb::BlockBasedTableFactory(table_options);
cf_options.table_factory.reset(table_factory);

Compression 压缩

压缩的主要目的是为了节省空间但却有读性能 以及 系统CPU和 磁盘I/O的额外消耗,因为需要将读到的datablock 进行解压,这个过程会有CPU的计算和I/O代价,所以这个配置选项是一个权衡。

rocksdb提供了不同压缩算法的选择:

  • cf_options.compression 这个配置控制的是前n-1层的压缩算法,建议使用lz4(kLZ4Compression)算法,如果不可用的话再选择snappy(kSnappyCompression)
  • cf_options.bottommost_compression 控制最后一层的压缩算法,建议使用ZStandard(kZSTD),如果不可用的话可以选择Zlib(kZlibCompression)

为什么要有这样的针对不同层的不同压缩算法的配置?
因为n-1层 的sst文件还是有比较高的概率被读到,所以空间的压缩比不需要那么高,为了降低压缩对系统资源和性能的消耗,编解码的效率则会优先考虑。但文件落到了第n层, 这个文件被读到的概率就比较低,可以设置相对较高的压缩比。

Compaction优化

关于Compaction 的原理及其所带来的问题,之前的多篇文章也有详细描述。
Rocksdb Compaction 源码详解(一):SST文件详细格式源码解析
Rocksdb Compaction源码详解(二):Compaction 完整实现过程 概览
Rocksdb 的 rate_limiter实现 – compaction限速
LSM 优化系列(三)SILK- Preventing Latency Spikes in Log-Structured Merge Key-Value Stores ATC‘19

这里也推荐大家使用rocksdb的Rate limiter进行限速,限速能够达到从I/O层面限制compaction的过程对系统资源CPU和IO的竞争的目的,从而保证客户端的请求无论是qps还是延时(当然qps和请求延时是有相关性的)能够较为平稳。

大家在使用rocksdb的过程中如果发现客户端的请求受到compaction的I/O 竞争,可以选择RateLimiter的配置接入。
通过如下配置进行设置:

db_options.rate_limiter.reset(rocksdb::NewGenericRateLimiter(rate_bytes_per_sec /* int64_t */,refill_period_us /* int64_t */,fairness /* int32_t */));

核心参数如下三个:

  • rate_bytes_per_sec 这个是最常用也是大家使用起来最有效的一个参数,用来控制compaction或者flush过程中每秒写入的量。比如,设置了200M, 表示当compaction 累积的总写入token达到 200M /s 时才会触发系统调用的write.
  • refill_period_us 用来控制 token 更新的频率;比如设置的rate_bytes_per_sec是10M/s, 且refill_period_us 设置的是100ms,那么表示 每100ms即可重新调用一次compaction的写入。针对1M的大value 可以立即写入,而小于1M的数据则需要消耗CPU, 累积到1M 触发一次写入。
  • fairness 表示低优先级请求获得处理的概率。
    RateLimiter 支持接受高优先级线程 和 低优先级线程的请求,一半flush操作是最高的优先级,其次是 L0 --> L1 compaction优先级较高,最后则是Higher Level compactions 优先级最低。那么这个参数 fairness表示 即使现在有较多的高优先级任务在调度,低优先级的任务也有 1 / fairness 的机会能够被调度,从而防止被饿死。

更加详细的原理实现可以参考:
Rocksdb 的 rate_limiter实现 – compaction限速

通过测试接入RateLimiter(限速128M),在100B 的9:1读写比场景,无压缩,单db 500G, blockcache 10G的配置下
L5的P9999 读延时由原来的120ms量级

降到了2-3ms的量级

具体的RateLimiter配置需要在实际场景中进行测试,如果写入量比较大,带来的compaction的量也会很大,相应的限速带宽应该更高。

通用workload的配置

下面的这一些配置也是社区提供的他们认为比较通用的配置,大家在检查的过程中会发现这一些配置和我们的默认配置还是有较大差异。 社区为了防止新老版本的db 配置差异导致的一些问题,所以基本没有怎么修改过默认rocksdb的配置项,一直沿用最初的默认配置。

如果用户需要重新加载一个 新的db,那么建议使用这里的配置,能够有较好的性能提升,并不建议直接在旧的db上应用。

基本的配置选项如下:

// 动态调整L0--Ln的大小,保证L0-->L1能够及时刷新,不会因为容量不足而阻塞上层的flush。能够比较好得维护
// LSM tree的树状结构
cf_options.level_compaction_dynamic_level_bytes = true;// 最大compaction的线程数
options.max_background_compactions = 4;
options.max_background_flushes = 2;// flush/compaction 每次sync的数据量,即data block累计达到1M 触发一次sync
options.bytes_per_sync = 1048576;// compaction 过程中选择文件的优先级,能够降低写放大
// 配置了这个参数,会优先选择和下一层sst文件覆盖度较低的文件进行compaction,减少compaction过程中被反复读出写入
options.compaction_pri = kMinOverlappingRatio; // 设置block_size,这里的block是指sst文中的一个个数据block(data,index,filter,meta,range del)
table_options.block_size = 16 * 1024;
table_options.cache_index_and_filter_blocks = true;
table_options.pin_l0_filter_and_index_blocks_in_cache = true;

以上通用的配置就社区的推荐 以及 实际测试过程中发现 并不会有成倍的性能提升, 在不同的通用workload下拥有较好的性能。

所以如果拥有较强的研发实力 以及 对特定的业务场景拥有强需求 ,那么对rocksdb进行定制化改造是一个更加合适的选择。就像阿里的x-engine,针对电商业务的洪峰,泄洪,洋流三个问题 进行了LSM 重写,这样的优化在特定的业务场景所产生的收益肯定比通用的rocksdb的收益来的更加彻底。

Rocksdb 的一些参数调优策略相关推荐

  1. JVM面试问题系列:JVM 配置常用参数和常用 GC 调优策略

    JVM 配置常用参数 堆参数 回收器参数 如上表所示,目前主要有串行.并行和并发三种,对于大内存的应用而言,串行的性能太低,因此使用到的主要是并行和并发两种.并行和并发 GC 的策略通过 UsePar ...

  2. 45.JVM调优策略、常见问题:内存泄漏(年老代堆空间被占满、持久代被占满、堆栈溢出、线程堆栈满、系统内存被占满)优化方法:优化目标、优化GC步骤、优化总结;案例分析(公司系统参数、网上给的配置参数)

    45.JVM调优策略 45.1.常见问题 45.1.1.内存泄漏 45.1.1.1.年老代堆空间被占满 45.1.1.2.持久代被占满 45.1.1.3.堆栈溢出 45.1.1.4.线程堆栈满 45. ...

  3. 【Flink】Flink on RocksDB 参数调优指南

    1. 背景 对于需要保存超大状态(远超于内存容量)的流计算场景来说,目前 RocksDB [1] 是 Flink 平台上官方实现的唯一选择.业界也有使用 Redis 等其他服务作为状态后端的方案,但终 ...

  4. Flink on RocksDB 参数调优指南

    对于需要保存超大状态(远超于内存容量)的流计算场景来说,目前 RocksDB [1] 是 Flink 平台上官方实现的唯一选择.业界也有使用 Redis 等其他服务作为状态后端的方案,但终究不够成熟, ...

  5. RocksDB参数调优

    文章目录 一.前言 二.RocksDB关键性能指标 1. 写放大 2. 读放大 3. 空间放大 三.测试机型 四.性能分析 1. 写性能 - 异步写入1千万个连续key 2. 写性能 - 异步写入1千 ...

  6. 常用MySQ调优策略及相关分享:学习随记

    最高¥2000云产品通用代金券,访问链接注册.实名认证后可领取 https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=dan ...

  7. Java常见面试题:常用 GC 调优策略有哪些?

    常用 GC 调优策略有哪些? GC 调优原则: GC 调优目的: GC 调优策略: GC 调优原则 在调优之前,我们需要记住下面的原则: 多数的 Java 应用不需要在服务器上进行 GC 优化: 多数 ...

  8. 【宋红康 MySQL数据库 】【高级篇】【15】数据库其它调优策略

    持续学习&持续更新中- 学习态度:守破离 [宋红康 MySQL数据库 ][高级篇][15]数据库其它调优策略 数据库调优的措施 调优的目标 如何定位调优问题 调优的维度和步骤 优化MySQL服 ...

  9. Java架构学习(十二)java内存结构新生代老年代JVM参数调优堆内存参数配置解决堆栈溢出

    JVM参数调优与垃圾回收机制 一.java内存结构 Java内存模型:是多线程里面的,jmm与线程可见性有关 Java内存结构:是JVM虚拟机存储空间. Java内存结构图 Java内存机构分为:方法 ...

最新文章

  1. hdu2159 FATE
  2. Asp.net的用户管理
  3. C++各大著名程序库
  4. 8-Trusted Board Boot
  5. 阿里云安全运营中心:DDoS攻击趁虚而入,通过代理攻击已成常态
  6. 使用ArcGIS Engine来实现地图的点击查询并闪烁
  7. 个性化联邦学习PFedMe详细解读(NeurIPS 2020)
  8. 详解MariaDB数据库的事务
  9. screen,client,page三种确定鼠标坐标的区别和原生JS事件写法,区别于Jquery的$.on(x,y);和$.click()...
  10. The idea of ​​router network configuration
  11. T-SQL 之 DDL语法
  12. [转载]高效程序员应该养成的七个习惯
  13. Android权限管理 1
  14. stdafx.h头文件代码
  15. 宠物游戏系统 java
  16. Android与51822蓝牙模块通信流程的实现与分析
  17. 通俗理解三维向量的点乘与叉乘
  18. 转:著名的100个管理定律点评8 - 竞争决胜的智慧与策略
  19. mysql 5.7 lbs_使用mysql来实现lbs(地理位置服务)功能
  20. shell编写的天气预报桌面小程序

热门文章

  1. python基础:python扩展包的安装方式
  2. ionic中的后退方法
  3. JAVA-Eclipse快捷键
  4. 下一版本Windowsreg; CE 开发工具Smart Device Extensions for Microsoft Visual Studioreg; .NET...
  5. SVO中 Inverse Compositional Image Alignment方法的学习笔记
  6. express给html设置缓存,webpack + express 实现文件精确缓存
  7. php true true true,php-为什么此评估为true
  8. java将实体类转化为json_只有实践才能将知识转化为智慧
  9. libc.so.6 is needed by mysql_libc.so.6(GLIBC_2.14)(64bit) is needed by…问题的解决办法
  10. char的初始值_java从入门到放弃 各种数组的初始值?