KVell: the Design and Implementation of a Fast Persistent Key-Value Store
1.Background
传统的存储设备和CPU之间存在巨大的速度差异,随机访问和顺序访问之间也存在巨大的速度差异。
访存速度是KVs的瓶颈。为此通过投入一些CPU时钟周期去优化访存的速度是一种良好的策略。为了提高访存速度,传统的KVs通过投入一些消耗CPU的操作,避免随机访问实现顺序访问,如数据在磁盘上的有序性和同步等操作。
LSM-Tree的工作原理,因为以前比较细致的讲过这里不再讲。
现代的块寻址的SSD设备提供了非常高的带宽,相似的随机和顺序读写性能。
2.Problem
1.传统的KVs没有考虑新型SSD的新特性,原有的一些优化反而加重了CPU的负担,得CPU成为了KVs的瓶颈。
RocksDB:CPU的60%的时间都需要花费在Compaction上(合并:28%;构建索引:15%;剩下的时间用于:读写磁盘数据 )
B-tree:CPU的主要开销在同步操作上,47%的时间用于等待日志的插槽(全局的序列号更新的不够快);12%的时间用于从page cache中evication dirty data;5%的时间用于管理commit log;25%的时间用于内核读写调用;18%的时间用于执行客户端请求;
B∈ tree:CPU的主要开销在同步操作上,30%的时间用于锁或者原子操作用于保护共享页;多于20%的时间用于将数据从buffer移动到在磁盘上所在的位置。
2.LSM 和 B tree KVs会有显著的性能波动(延迟也会波动,可能导致尾延迟大),也会导致性能和尾延迟不好预测。
LSM tree:updates 需要等待compactions完成(第一层满,原因还是在于compaction消耗大量cpu,cpu是瓶颈)
B tree:evictions 操作不够快。
LSM 和 B tree其根本原因都在于其维护操作不够快从而导致客户端请求阻塞。
3.Motivation
1.针对新设备的特性设计出一种能够充分利用磁盘带宽的KVs设计准则。
2.新的KVs应该更加关注如何充分利用CPU
4.KVell design principles
强调CPU的低开销
4.1Share nothing
目的:不共享有助于并行和最小化各个线程之间通信的CPU开销;
实现机制:每个线程独立的处理读写请求,每个线程只负责处理给定keys集合的一个子集,每个线程维护了一个私有的数据结构去管理这个key的子集。
数据结构包括:
- 在内存中的轻量级索引:B-Tree索引用于追踪key在持久化存储上的位置
- I/O队列:有效地存储和从持久存储器中检索信息。
- Free list:在内存中的磁盘块列表,其中记录了适合存储项的空闲位置。
- page cache:使用自己的页面缓存,不使用OS的。
扫描操作是唯一需要线程同步的操作
Share nothing 通过分区来实现,但分区的请求可能导致负载不均衡。
作者声称通过适当的分区影响很微小。
4.2Do not sort on disk,but keep indexes in memory
目的:减少key插入(不需要先找到合适的位置)的开销,消除维护磁盘上的数据结构的CPU开销。
每个工作线程不需要对它工作集中的key进行排序,直接将它存储到磁盘上的最终位置,可以有效降低写操作的延迟。
4.3Aim for fewer syscalls,not for sequential I/O
目的:使用批处理随机I/O,随机I/O是为了消除原有为了实现顺序I/O而浪费的CPU时钟周期,批处理是为了减少系统调用次数从而减少CPU开销。
批处理随机I/O:在新型SSD上顺序I/O≈随机I/O,所以采用随机I/O。批处理需要在peak IOPS和latency之间进行权衡。
每个工作线程只能将文件存储在一个磁盘上。这样做的考虑是限制每个磁盘上的请求数量。
因为share nothing的设计,所以各个工作线程之间不会通信,他们不能知道其它工作线程给某个磁盘发送了多少请求。
- 如果每个工作线程只能将数据存储到一个磁盘上,那这个磁盘上的最多请求数为batch size * 该磁盘上的工作线程数。
- 如果每个工作线程能将数据存储到所有的磁盘上,那一个磁盘上的最多请求数为batch size * 所有的工作线程数。
对于倾斜的工作负载,会不会导致负载不均衡?
请求分发给工作线程是根据他们的key值,此外工作线程只访问一个磁盘,可能存在一个倾斜的工作负载(大部分data都访问同一个磁盘,从而让其它磁盘空闲)
作者说:在倾斜的工作负载中,数据倾斜会被内部页缓存吸收。**大多数**负载不平衡不会导致磁盘I/O。
4.4No commit log
KVell:只有当数据持久化到磁盘上以后才会承认更新,所以不需要提交日志。
不采用提交日志可以充分利用磁盘带宽去处理客户端处理请求。
5.KVell implementation
https://github.com/BLepers/KVell
5.1Client operations interface
writes: Update(k,v); reads: Get(k);Scan(k1,k2);
5.2On-disk data structures
目的:为了避免磁盘碎片化,将item放入与item大小想匹配的file/slab中。
KVell以块粒度访问slabs,它的大小跟page一样大(4KB)。
如果item size 小于 page size,KVell会在slab的item前添加时间戳、key size和value size等信息。
如果item size大于 page size,在其所使用的每个块的开始位置添加时间戳头。
对于更新操作:
- item size < page size: 就地更新
- item size > page size: 将更新追加到slab中,然后在原来的位置写入tombstone。
- item size发生改变:首先在新的slab中写入item,接下来删除旧的item。
5.3 In-memory data structures
Index
目的:查询item在磁盘上的位置。
KVell为每个工作线程创建了一个在内存中的索引(用来存储磁盘上项的位置)。
Items通过它们的前缀进行所以,没有采用hash的原因是为了方便扫描操作。
对于中型和大型的items,B树的性能差,占据过多的内存空间。
prefix、location information、B-tree structure
Page cache
目的:避免频繁访问持久化存储设备。
页面缓存会记录缓存了索引中那个page和那些page按照LRU的顺序从cache中被驱逐。
Free list
free list = slab’s free list,一些已经释放的slab list/stack。
当删除一个item时,它所在的slab会被插入每个slab在内存中的堆栈(slab’s free list),同时在item 在disk上的位置写入tombstone。
限制在内存中的大小,同时保留批处理I/O一次重用多个块的能力(不需要额外的磁盘访问)。
有点疑问,看完源码再分析
5.4 Efficiently performing I/O
采用AIO,通过批处理的方式,可以决定队列深度,通过多个请求来摊分系统调用的开销。
MMap I/O依赖于OS级的page cache、所以当数据集不能全部装入RAM中时,内核需要进行频繁的map和un-map页面替换,影响CPU性能。
单线程:一次只能发出一个磁盘读请求;脏页定期刷新到磁盘上会导致I/O的爆发,SSD队列深度大部分时间处于次优状态;
多线程:当页面LRU时,需要lock;使TLB条目无效;使所有访问过该page的核上的虚拟地址到物理地址的映射无效,产生显著的IPI通信开销。
Direct I/O:同步的I/O,不需要处理复杂的map和un-map问题。
5.5 Client operation implementation
update:modify就地modify;delet的value = tombstone,将其slab加入free list中;add有空闲块则重用,没有则append。
scan:1从索引中获取keys的位置;2读相应的页;KVell需要扫描所有线程的索引,对所有索引进行加锁,然后轮流解锁。
5.6 Failure model and recovery
当系统崩溃时,通过扫描所有的slab块然后重新构建在内存中的索引。
如果一个item被扫描到两次,选择将most recent item保存在内存索引中,另一个释放掉。
如果item大于block size,KVell使用timestamp headers去驱除只被部分写入的项。
5.Evaluation
KVell: the Design and Implementation of a Fast Persistent Key-Value Store相关推荐
- Design and Implementation of a Highly Efficient DGEMM for 64-bit ARMv8 Multi-Core Processors
Design and Implementation of a Highly Efficient DGEMM for 64-bit ARMv8 Multi-Core Processors 针对64位 A ...
- The Design and Implementation of Open vSwitch
文章名称:The Design and Implementation of Open vSwitch 文章来源:Pfaff B , Pettit J , Koponen T , et al. The ...
- plsql 存储过程 批量提交_新一代的键值存储 KVell SOSP 2019
『看看论文』是一系列分析计算机和软件工程领域论文的文章,我们在这个系列的每一篇文章中都会阅读一篇来自 OSDI.SOSP 等顶会中的论文,这里不会事无巨细地介绍所有的细节,而是会筛选论文中的关键内容, ...
- 数据存储策略——lsm-tree
文章目录 一.背景 二.lsm-tree简介 三.lsm-tree设计思想 四.lsm-tree原理 1.写操作 2.读操作 3.有序表持久化 4.后台压缩 五.lsm-tree的应用 六.lsm-t ...
- C/C++ 框架,类库,资源集合
很棒的 C/C++ 框架,类库,资源集合. Awesome C/C++ Standard Libraries Frameworks Artificial Intelligence Asynchrono ...
- golang 开源项目全集
一直更新中,地址:https://github.com/golang/go/wiki/Projects#zeromq Indexes and search engines These sites pr ...
- springboot萌宠宠物网店的开发与设计 毕业设计-附源码011042
SSM萌宠宠物网店的设计与实现 摘要 在社会快速发展的影响下,宠物用品业继续发展,大大增加了宠物用品的数量.多样性.质量等等的要求,使萌宠宠物网店的管理和运营比过去十年更加困难.依照这一现实为基础,设 ...
- (附源码)springboot萌宠宠物网店的开发与设计 毕业设计 011042
SSM萌宠宠物网店的设计与实现 摘要 在社会快速发展的影响下,宠物用品业继续发展,大大增加了宠物用品的数量.多样性.质量等等的要求,使萌宠宠物网店的管理和运营比过去十年更加困难.依照这一现实为基础,设 ...
- SSM萌宠宠物网店毕业设计源码011042
SSM萌宠宠物网店的设计与实现 摘要 在社会快速发展的影响下,宠物用品业继续发展,大大增加了宠物用品的数量.多样性.质量等等的要求,使萌宠宠物网店的管理和运营比过去十年更加困难.依照这一现实为基础,设 ...
最新文章
- jvm性能调优实战 - 34十万QPS的社交APP 如何优化GC性能提升3倍?
- windows安装spark工具记录
- js jquery 函数回调
- iframe懒加载_前端常见问题
- signature=f7a4b29b93ef2b36608792fdef7f454a,Embedding of image authentication signatures
- C++ 读取结束的判断
- java 不生成文件下载_java 下载文件时怎么避免在服务器上生成文件
- 【路面分类】基于matlab灰度共生矩阵图形纹理检测+SVM路面状况分类【含Matlab源码 1519期】
- C语言笔记 清屏(循环时不一闪一闪的) 光标移动到任意位置 带注释(详细)
- 树莓派安装中文输入法(使用的谷歌提供的树莓派系统google voice kit)
- 网站被攻击了怎么办?
- linpack性能测试记录
- excel整行删除,图片一起删除
- MAC 设置忽略部分IP代理
- java基础知识复习(上半)
- 程序设计入门C语言 --- 素数和
- 初识Java ~ (二) # Java 中程序的执行流程,(万字长文)特别细~ 可收藏~
- void func()与 func(void)的区别
- jQuery笔记——UI
- 国外卫星地图 Sentinel Hub EO Browser的使用