rocksdb是在leveldb的基础上优化而得,解决了leveldb的一些问题。

主要的优化点

1.增加了column family,这样有利于多个不相关的数据集存储在同一个db中,因为不同column family的数据是存储在不同的sst和memtable中,所以一定程度上起到了隔离的作用。

2.采用了多线程同时进行compaction的方法,优化了compact的速度。

3.增加了merge operator,优化了modify的效率

4.将flush和compaction分开不同的线程池,能有效的加快flush,防止stall。

5.增加了对write ahead log(WAL)的特殊管理机制,这样就能方便管理WAL文件,因为WAL是binlog文件。

下面从几个小点来一窥rocksdb的微妙之处。

rocksdb的column family

column family的具体使用场景,官方并没有给出非常好的说明,rocksdb支持跨column family的原子写操作,说明官方认为column family的数据之间还是有一定的关系的,而column family的数据文件是分割开的,包括sst文件和memtable都是不会共用的,所以官方还是希望不同column family的数据进行隔离。所以我觉着一个应用场景就是不同的数据混跑在同一个db上,这个仅是个人感觉,欢迎大家讨论。那么不同column family之间会怎样互相干涉呢?

Q:多column family的flush是怎么进行线程分布的?

A:可以共用一个线程池,所以写的多的会多占用线程。也可以分开配置线程池(指定不同的env),这样就会不互相干扰。

Q:多column family的内存是怎么分配的?

A:内存主要有两方面,第一方面是write buffer,第二方面是block cache。

write buffer是每个column family单独享有的,block cache可以配置成column family级别,也可以配置成整个db的column family共享一个block cache,也可以配置成多个db共享一个block cache。

rocksdb的文件类型

主要有以下几种类型sst文件,CURRENT文件,manifest文件,log文件,LOG文件和LOCK文件

sst文件存储的是落地的数据,CURRENT文件存储的是当前最新的是哪个manifest文件,manifest文件存储的是Version的变化,log文件是rocksdb的write ahead log,就是在写db之前写的数据日志文件,LOG文件是一些日志信息,是供调试用的,LOCK是打开db锁,只允许同时有一个进程打开db。

ColumnFamilyOptions

  这些option都是column family相关的,可以对不同的column family赋不同的值。

  inplace_update_support: 字面含义是是否支持在原位置更新,如果支持的话,那么原来的数据就被擦除了,所以snapshot和iterator保留当时的数据的逻辑就没法实现了

  num_levels: 记录的是version的level的数目,默认是7,即0~6

  target_file_size_base: level1的sst文件的大小,默认为2MB

  target_file_size_multiplier: level1以上的sst文件大小,乘数因子默认是1,即所有level的文件大小都是2MB

    level0的文件大小是由write_buffer_size决定的,level1的文件大小是由target_file_size_base决定的,level2及以上,size = target_file_size_base * (target_file_size_multiplier ^ (L - 1))

  max_bytes_for_level_base: level1的sst总的文件总和大小,默认是10MB

  max_bytes_for_level_multiplier: level2及以上的level的sst文件总和大小的乘数因子,默认是10,

    level0的sst文件总和大小是level0_stop_writes_trigger * write_buffer_size,因为level0的文件数目达到level0_stop_writes_trigger时候就会停止write。

    level1及以上的文件总和大小是max_bytes_for_level_base * (max_bytes_for_level_multiplier ^ (L - 1)),默认的level0是4MB * 24 = 96MB,level1是10MB,level2是100MB,level3是1G,level4是10G。。。

rocksdb原子操作的实现

  rocksdb的一个WriteBatch是原子操作,要么全部成功,要么全部失败,具体的实现原理是在整个log的写的过程中只会调用Write操作,最后会调用一次flush,所以如果中间发生机器crash,所有的都会失败,否则所有的都会成功。

rocksdb写和读放大

  rocksdb的写会写WAL(Write Ahead Log),如果sync的话,会写一次磁盘,然后会写memtable

  写rocksdb的时候有可能会卡住,详见下面的rocksdb的写stall

  rocksdb的读,会首先读memtable,如果memtable没有找到的话,会读下面level的数据,由于level0的多个sst会有交叠,所以每个sst都会通过filemeta判断在不在最小和最大的范围内,如果在就需要读这个sst的文件内容,来查看,其他level的sst文件不会有数据交叠的情况,所以只会有一个文件可能含有这个数据。

  可以看出来读放大还是比较严重的。rocksdb为了减少读放大,增加了cache.

  读cache

    rocksdb的读cache分为两部分:table cache和block cache。这两个都是LRUCache

    block cache存储的block,包括index block和filter block(通过options可以配置)

    table cache存储的是table,是整个文件的meta信息和Foot信息。table_cache_size的消耗内存的大小是有Options里面的max_open_files决定的。

  bloomfilter:

    bloomfilter的增加并不能减少写放大,因为bloomfilter是table范围的或者block范围的,而且bloomfilter是存储在文件中的,那么必须把这些从文件里面读出来后才能起到作用。

rocksdb的版本管理

rocksdb的版本相关的数据结构有Version、VersionStorageInfo、VersionBuilder、VersionEdit、SuperVersion和VersionSet。

VersionEdit描述的是版本的变更,其主要操作为AddFile和DeleteFile,分别表示,在某个level上增加文件和删除文件,都是版本变更的操作。

VersionBuilder是生成Version的工具,所以其有两个主要函数:

void Apply(VersionEdit* edit);
void SaveTo(VersionStorageInfo* vstorage);

分别是应用某个VersionEdit和将现在的版本Saveto某个VersionStorageInfo

VersionStorageInfo是Version的信息的存储结构,每一个Version的sst文件信息都保存在VersionStorageInfo。

Version是一个完整的版本。sst文件信息存储在VersionStorageInfo。可以在这个版本上Get数据。

SuperVersion是db的一个完整的版本包含的所有信息,包含当前的Memtable,imm和一个Version。也就是Version包含的是sst数据信息,SuperVersion包含的是Version的数据和memtable中的数据。

VersionSet是整个db的版本管理,并维护着manifest文件。每个column family的版本单独管理,在ColumnFamilyData这个数据结构里面有current Version。

rocksdb的Flush

Flush是指将memtable的数据导入到sst中,变成持久化存储,就不怕数据丢失了。

1.首先在memtable的add的时候,会检测是否memtable的大小达到了max write buffer,如果是就将should_flush_置为true,并会在WriteBatch的Handler里面调用CheckMemtableFull,将当前column family加入flush_scheduler。

2.在Write的时候,调用ScheduleFlushes,将需要flush的column family的memtable切换一个新的,同时将原来的memtable加入cfd的imm中,如果这个column family data的imm数量大于min_write_buffer_number_to_merge,并启动一个新的线程调用BGWorkFlush

由于真正的Flush过程是在另一个线程完成的,所以这个地方并不会block写过程

另外,如果total_log_size大于max_wal_log_size并且不是只有一个column family,也会触发flush,因为flush能将memtable持久化到磁盘上,同时对应的wal就可以删除了

rocksdb的compaction

rocksdb的compaction的触发条件有两类:

第一类是某一个level的数据太多

  1. VersionStorageInfo的compaction_score_的计算方法是level0的是当前文件数目/level0_file_num_compaction_trigger,其他层是该层当前文件大小总和/该层的配置的允许文件总和最大值
  2. 基于level的存储的compaction总的来说,就是一次挑选某一个level的一个文件,然后将该文件和高level的多个相交文件merge,最后生成多个高level的文件。具体的细节是:每次会挑选compaction score最高的一个level,并在这个level中找到一个文件大小最大,并且上一个level的相交文件没有在compaction的一个文件

第二类是seek太多

疑问:

如果option里面soft_rate_limit设置的为0.0和1之间,compaction并不会触发,但是会触发write delay,这是为什么?

rocksdb的写stall

在DBImpl也就是db的实例里面有一个WriteController,同时在ColumnFamilySet里面也有这个WriteController的指针,这个数据结构会控制db的写stall行为。

在ColumnFamily进行SuperVersion变更的时候(增加新memtable,flush增加sst,compaction)都会查看需不需要stall Write,stall的条件是:

1)imm的数量大于等于option允许的最大数目

2)level0的文件的数量大于option允许的数目

如果没有满足上面两项,但是compaction score比较大会delay写

rocksdb的write ahead log(WAL)

  1. 每次写操作,rocksdb会先写write ahead log,然后才会写db
  2. write ahead log可以配置到单独的空间,并且可以配置WAL文件的单独的删除机制。这种原因是为了保存WAL文件,达到特殊的目的,比如,其他sst文件放在不可靠存储里面,而WAL放到可靠存储里面。

rocksdb的缺点

1.column family之间的隔离做的不是非常好,因为一个db只有一个WriteController,那么一旦一个db中的一个column family发生了阻塞,比如写太快,那么就会阻塞其他的column family的写。

2.多进程compaction和flush的效果我持怀疑态度,因为这两个主要是磁盘操作,多进程并不会有很好的效果。

转载于:https://www.cnblogs.com/jfwang/p/4432905.html

rocksdb学习笔记相关推荐

  1. RocksDB 学习笔记

    RocksDB是FaceBook起初作为实验性质开发的一个高效数据库软件,旨在充分实现快存上存储数据的服务能力.RocksDB的主要设计点是在快存和高服务压力下性能表现优越,支持point looku ...

  2. cockroachdb mysql_CockroachDB学习笔记——[译]CockroachDB中的SQL:映射表中数据到键值存储...

    CockroachDB学习笔记--[译]CockroachDB中的SQL:映射表中数据到键值存储 原文标题:SQL in CockroachDB: Mapping Table Data to Key- ...

  3. JavaEE 企业级分布式高级架构师(二十)RocketMQ学习笔记(2)

    RocketMQ学习笔记 进阶篇 消息样例 普通消息 消息发送 发送同步消息 发送异步消息 单向发送消息 三种发送方式的对比 消费消息 顺序消息 如何保证顺序 顺序的实现 MessageListene ...

  4. StreamX学习笔记之StreamAPI开发应用

    文章目录 项目配置 项目结构 assembly\bin目录 setclasspath.sh shutdown.sh startup.sh streamx.sh logback.xml applicat ...

  5. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  6. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  7. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  8. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  9. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

最新文章

  1. 面向生信分析的高性 RStudio 服务器
  2. 【PC工具】200412更新百度网盘下载工具——最终最简单百度网盘下载方法及注意事项...
  3. datetimepicker控件怎么改变hover颜色_VBA入门课程,ActiveX控件系列知识,复合框的属性与常见VBA代码...
  4. svn clean up 出错解决方案
  5. x光肺部分割数据集_吴恩达发布了大型X光数据集,斯坦福AI诊断部分超越人类 | AAAI 2019...
  6. 帆软已知年和第几周,算出7天日期如何写?
  7. 像在K8S集群中一样运行本地程序
  8. InfoQ编辑2018年推荐阅读清单(第二部分)
  9. Sql Server2005创建数据库
  10. 网上购物系统数据库分析
  11. 【工具类】java数字金额转换成大写
  12. js对象定义的3种方法
  13. 搭建FTP资源服务器
  14. 自定义chromium浏览器
  15. oracle job remove,如何删除oracle Job命令实例
  16. 并发调度的可串行性:可串行化调度、冲突可串行化调度、两段锁协议
  17. git 如何把develop分支代码合并到master主分支
  18. 作为Fab-Liter战略的一部份,安森美剥离晶圆制造厂
  19. WP博客几款好看的图片类模板分享
  20. 如何给导师发邮件?【附带邮件模板】

热门文章

  1. 如何在 Outlook 中使用外出时的助理程序
  2. 多线程测试工具groboutils的使用
  3. Android AOSP基础(五)不会调试系统源码,还搞什么Android?
  4. 状态很差时,就不要再继续做了。因为是徒劳,再就是过段时间或第二天再看,会豁然开朗,原来存在的疑难问题都迎刃而解。平时没事的时候要不断地给自己充电,让自己了解多方面知识。...
  5. Tarjan水题系列(2):HNOI2012 矿场搭建
  6. JavaScript学习备忘
  7. 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
  8. POJ 1320 Street Numbers 解佩尔方程
  9. p中div -- a中a
  10. 【读书笔记】程序员的自我修养总结(一)