rocksdb学习笔记
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的数据太多
- VersionStorageInfo的compaction_score_的计算方法是level0的是当前文件数目/level0_file_num_compaction_trigger,其他层是该层当前文件大小总和/该层的配置的允许文件总和最大值
- 基于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)
- 每次写操作,rocksdb会先写write ahead log,然后才会写db
- 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学习笔记相关推荐
- RocksDB 学习笔记
RocksDB是FaceBook起初作为实验性质开发的一个高效数据库软件,旨在充分实现快存上存储数据的服务能力.RocksDB的主要设计点是在快存和高服务压力下性能表现优越,支持point looku ...
- cockroachdb mysql_CockroachDB学习笔记——[译]CockroachDB中的SQL:映射表中数据到键值存储...
CockroachDB学习笔记--[译]CockroachDB中的SQL:映射表中数据到键值存储 原文标题:SQL in CockroachDB: Mapping Table Data to Key- ...
- JavaEE 企业级分布式高级架构师(二十)RocketMQ学习笔记(2)
RocketMQ学习笔记 进阶篇 消息样例 普通消息 消息发送 发送同步消息 发送异步消息 单向发送消息 三种发送方式的对比 消费消息 顺序消息 如何保证顺序 顺序的实现 MessageListene ...
- StreamX学习笔记之StreamAPI开发应用
文章目录 项目配置 项目结构 assembly\bin目录 setclasspath.sh shutdown.sh startup.sh streamx.sh logback.xml applicat ...
- PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call
您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...
- 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 2020年Yann Lecun深度学习笔记(下)
2020年Yann Lecun深度学习笔记(下)
- 2020年Yann Lecun深度学习笔记(上)
2020年Yann Lecun深度学习笔记(上)
最新文章
- 面向生信分析的高性 RStudio 服务器
- 【PC工具】200412更新百度网盘下载工具——最终最简单百度网盘下载方法及注意事项...
- datetimepicker控件怎么改变hover颜色_VBA入门课程,ActiveX控件系列知识,复合框的属性与常见VBA代码...
- svn clean up 出错解决方案
- x光肺部分割数据集_吴恩达发布了大型X光数据集,斯坦福AI诊断部分超越人类 | AAAI 2019...
- 帆软已知年和第几周,算出7天日期如何写?
- 像在K8S集群中一样运行本地程序
- InfoQ编辑2018年推荐阅读清单(第二部分)
- Sql Server2005创建数据库
- 网上购物系统数据库分析
- 【工具类】java数字金额转换成大写
- js对象定义的3种方法
- 搭建FTP资源服务器
- 自定义chromium浏览器
- oracle job remove,如何删除oracle Job命令实例
- 并发调度的可串行性:可串行化调度、冲突可串行化调度、两段锁协议
- git 如何把develop分支代码合并到master主分支
- 作为Fab-Liter战略的一部份,安森美剥离晶圆制造厂
- WP博客几款好看的图片类模板分享
- 如何给导师发邮件?【附带邮件模板】
热门文章
- 如何在 Outlook 中使用外出时的助理程序
- 多线程测试工具groboutils的使用
- Android AOSP基础(五)不会调试系统源码,还搞什么Android?
- 状态很差时,就不要再继续做了。因为是徒劳,再就是过段时间或第二天再看,会豁然开朗,原来存在的疑难问题都迎刃而解。平时没事的时候要不断地给自己充电,让自己了解多方面知识。...
- Tarjan水题系列(2):HNOI2012 矿场搭建
- JavaScript学习备忘
- 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
- POJ 1320 Street Numbers 解佩尔方程
- p中div -- a中a
- 【读书笔记】程序员的自我修养总结(一)