概述

MyRocks的memtable默认是skiplist,其大小和个数分别由参数write_buffer_size和max_write_buffer_number控制。数据写入时先写入active memtable, 当active memtable写满时,active memtable会转化为immutable memtable. immutable memtable数据是不会变化的,最终会刷入level0的sst文件中。

memtable 内存分配

RocksDB有自己的内存分配机制,称为Arena. Arena由固定的inline_block_和动态的blocks_组成。 inline_block_固定为2048bytes, blocks_由一系列的block组成,这些block大小一般为KBlockSize, 但从arena申请较大内存时(> KBlockSize/4)单独分配一个所申请大小的block. KBlockSize由参数arena_block_size指定,arena_block_size 不指定时默认为write_buffer_size的1/8.

这里有两个重要的概念

  • blocks_memory_
  • Arena当前已分配的内存
  • alloc_bytes_remaining_
  • Arena当前block已分配但未使用的内存,注意不是整个Arena已分配而未使用的内存

RocksDB在实际使用内存中用的是ConcurrentArena, 它是在Arena的基础上封装,是线程安全的。 同时ConcurrentArena为了提高并发对内存进行了分片,分片数由cpu个数决定,例如cpu核数为24, 则分片数为32,以下是分片的算法

// find a power of two >= num_cpus and >= 8 auto num_cpus = std::thread::hardware_concurrency();index_mask_ = 7;while (index_mask_ + 1 < num_cpus) {index_mask_ = index_mask_ * 2 + 1;}shards_.reset(new Shard[index_mask_ + 1]);

每个分片都有已分配但未使用的内存, 分片越多浪费的内存越多。

一个有趣的例子

测试环境:CPU核数64,write_buffer_size=1G, arena_block_size=0 根据前面的算法,CPU核数64, 内存分片数为64, arena_block_size 默认为write_buffer_size的1/8,对齐后是131072000

我们用1200个连接进行并发插入,这样能够充分使用内存分片数 这是测试某个瞬间取得的内存数据

allocated_memory:1179650048
AllocatedAndUnused:1172297392
write_buffer_size:1048576000
BlockSize:131072000 

注意AllocatedAndUnused和allocated_memory是如此的接近,也就是说存在巨大的内存浪费。然而这不是最严重的,更严重的是这种情况导致memtable的切换,后面会进行分析。

memtable 切换

memtable 发生切换的条件有

  1. memtable内存超过write_buffer_size会切换
  2. WAL日志满,WAL日志超过rocksdb_max_total_wal_size,会从所有的colomn family中找出含有最老日志(the earliest log containing a prepared section)的memtable进行切换,详见HandleWALFull
  3. Buffer满,全局的write buffer超过rocksdb_db_write_buffer_size时,会从所有的colomn family中找出最先创建的memtable进行切换,详见HandleWriteBufferFull
  4. flush memtable前会切换memtable, 下节会介绍

下面详细介绍memtable满切换

  • memtable 满切换

memtable内存超过write_buffer_size会切换,由于arena的内存使用,memtable控制内存使用的算法更加精细,切换条件从源码中很容易理解

bool MemTable::ShouldFlushNow() const {// This constant variable can be interpreted as: if we still have more than // "kAllowOverAllocationRatio * kArenaBlockSize" space left, we'd try to over // allocate one more block. const double kAllowOverAllocationRatio = 0.6;// If arena still have room for new block allocation, we can safely say it // shouldn't flush. auto allocated_memory = table_->ApproximateMemoryUsage() +range_del_table_->ApproximateMemoryUsage() +arena_.MemoryAllocatedBytes();// if we can still allocate one more block without exceeding the // over-allocation ratio, then we should not flush. if (allocated_memory + kArenaBlockSize <moptions_.write_buffer_size +kArenaBlockSize * kAllowOverAllocationRatio) {return false;}// if user keeps adding entries that exceeds moptions.write_buffer_size, // we need to flush earlier even though we still have much available // memory left. if (allocated_memory > moptions_.write_buffer_size +kArenaBlockSize * kAllowOverAllocationRatio) {return true;}return arena_.AllocatedAndUnused() < kArenaBlockSize / 4;
}

而上一节举出的例子正好符合切换的条件,正如前面所说的,内存都分配好了,还没来得及使用就发生切换了,白忙活了一场。

这里的现象是虽然write_buffer_size是1G,但最后刷到level0的sst都远远小于1G。

那么如何避免这种情况呢

  • 减少内存分片数,不建议
  • 调小arena_block_size, 亲测可用

这里有一个原则是arena_block_size*内存分片数应该小于write_buffer_size

  • memtable 切换实现
  1. NewWritableFile //创建日志文件
  2. ConstructNewMemtable //创建memtable
  3. cfd->imm()->Add(cfd->mem(), &context->memtables_to_free_); //设置immutable
  4. cfd->SetMemtable(new_mem); //设置新的memtable

flush memtable

immutable memtable会不断flush到level0的SST文件中

触发flush的条件有

  • WAL日志满,WAL日志超过rocksdb_max_total_wal_size,会从所有的colomn family中找出含有最老日志(the earliest log containing a prepared section)的column family进行flush,详见HandleWALFull
  • Buffer满,全局的write buffer超过rocksdb_db_write_buffer_size时,会从所有的colomn family中找出最先创建的memtable的column family进行flush,详见HandleWriteBufferFull
  • 手动设置参数force_flush_memtable_now/rocksdb_force_flush_memtable_and_lzero_now时
  • CompactRange时
  • 创建checkpoint时
  • shutdown时avoid_flush_during_shutdown=0会flush所有memtable

other

rocksdb中设置max_background_flushes=-1可以禁止flush,而MyRocks中rocksdb_max_background_flushes最小值限制为0. 因此,MyRocks若要禁止flush需放开此限制。

MySQL · myrocks · MyRocks之memtable切换与刷盘相关推荐

  1. MySQL数据和日志的刷盘机制以及双一配置

    详细介绍了MySQL数据和日志的刷盘机制以及双一配置,双一配置可以保证Mysql日志数据不丢失. 文章目录 1 内存数据的刷盘机制 2 MySQL数据的刷盘 2.1 刷盘数据来源 2.2 脏页以及刷盘 ...

  2. 三种中间件的刷盘(持久化)策略

    这里讨论Mysql(redolog).Redis(AOF).RabbitMQ(消息持久化) 三者的共同点都是:先在内存缓冲池中追加记录.以一定的频率刷盘持久化.批量刷盘都存在数据丢失的风险 刷盘(从内 ...

  3. mysql部署策略_MySQL延迟问题和数据刷盘策略流程分析

    一.MySQL复制流程 官方文档流程如下: MySQL延迟问题和数据刷盘策略 1.绝对的延时,相对的同步 2.纯写操作,线上标准配置下,从库压力大于主库,最起码从库有relaylog的写入. 二.My ...

  4. 怎么处理MySQL延迟问题和数据刷盘?

    一.MySQL复制流程 官方文档流程图如下: 1.绝对的延时,相对的同步 2.纯写操作,线上标准配置下,从库压力大于主库,最起码从库有relaylog的写入. 二.MySQL延迟问题分析 1.主库DM ...

  5. mysql数据刷盘过程详解_MySQL延迟问题和数据刷盘策略流程分析

    一.MySQL复制流程 官方文档流程如下: MySQL延迟问题和数据刷盘策略 1.绝对的延时,相对的同步 2.纯写操作,线上标准配置下,从库压力大于主库,最起码从库有relaylog的写入. 二.My ...

  6. mysql刷盘机制详解

    目录 刷盘机制总览 log buffer(innodb的,由存储引擎分配) binlog cache(由server分配) buffer pool 自适应刷脏页Adaptive Flushing 刷盘 ...

  7. mysql刷盘命令_MySQL延迟问题和数据刷盘

    导读 这篇文章主要介绍了MySQL延迟问题和数据刷盘策略流程分析,本文要给大家提到了mysql复制流程,需要的朋友可以参考下 一.MySQL复制流程 官方文档流程如下: MySQL延迟问题和数据刷盘策 ...

  8. mysql数据刷盘_MySQL延迟问题和数据刷盘策略

    一. MySQL 复制流程 官方文档流程图如下: 1.绝对的延时,相对的同步 2.纯写操作,线上标准配置下,从库压力大于主库,最起码从库有relaylog的写入. 二.MySQL延迟问题分析 1.主库 ...

  9. 针对 MySQL/InnoDB 刷盘调优

    原文 https://www.percona.com/blog/2020/05/14/tuning-mysql-innodb-flushing-for-a-write-intensive-worklo ...

最新文章

  1. 程序员福音-定时提醒bat
  2. python基础语法总结-Python基础语法精心总结!看完都知道的可以往下继续学习了...
  3. PHP 解析xml(包含非英文字符)
  4. 常见错误 不能打开注册表关键字
  5. 十大经典排序算法2(Python版本)
  6. Unet实现文档图像去噪、去水印
  7. 【转】Javascript 的词法作用域、调用对象和闭包
  8. VC++学习(5):文本编程
  9. 李雅普诺夫指数的计算
  10. 交流电中为什么要用相量法?
  11. 电路设计中如何解决电压跌落
  12. react利用react-activation实现子路由缓存
  13. Data Masking-克隆“真实”的假数据
  14. 我用Python告诉你,充气娃娃什么感觉,呜呜呜
  15. 遵化有教php基础知识,2019年河北省唐山市遵化市中小学语文教师招聘/编制考试历年真题试卷及答案解析...
  16. ck属于哪个集团_CK有几个品牌缩写?中国CK有几个品牌缩写?CK是什么品牌?CK 这个牌子的全名是什么啊?...
  17. 拐弯抹角FALSE-实验吧
  18. 三菱FX3U与4台三菱变频器专用指令通讯案例
  19. web静态页面-MIUI米柚
  20. php设置浏览次数,【php】集思广益,关于有效浏览次数的计算,大家都是如何来做呢?...

热门文章

  1. Caffe源码中common文件分析
  2. 【视频】V4L2之ioctl
  3. linux驱动:音频驱动(五)ASoc之codec驱动
  4. php修改时区MST,4、修改Cacti绘图的时间精度
  5. easyexcel生成excel_阿里JAVA解析Excel工具easyexcel
  6. 学生管理系统(C语言版)
  7. c语言子程序return,c语言return返回到哪
  8. input输入框为number类型时,去掉上下小箭头
  9. oracle数据导出方法,oracle多种导入导出数据方法
  10. flutter报错Could not connect to lockdownd, error code -