不啰里啰嗦了,关于leveldb、rocksdb的实现细节有兴趣的朋友自己搜搜,当然我后期会整理下leveldb的大概实现原理,我曾经花过不少心力还研究leveldb、rocksdb的设计及代码实现,受益匪浅的! 时常会回忆起leveldb的Lsm、Memtable、SStable、Manefest、log的设计。 正是因为懂了这些原理后你才更有把握在生产环境中使用rocksdb,也能分析出写快读慢的根本原因,规避和优化使用方法。

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新.  

http://xiaorui.cc/?p=4406

我们知道Rocksdb的数据结构其实很简单,就是单纯的KV,结构上是redis string那样的。 但他又跟redis不一样,首先他是可以数据落盘的,他也没有server封装,不管是对于python、golang语言来说,只是个C的扩展API而已。


上次有说过如何在rocksdb里面设计丰富多样的数据结构,方向上尽量跟redis的命令集靠拢的。 到现在为止,我已经在不少线上业务场景中用过rocksdb了,比如爬虫页面去重、缓存、监控历史数据。 准确的说,不全是rocksdb,也有用过它的前身leveldb。  我当初参考了ardb和ssdb的一些数据结构设计,去掉server层直接在python封装了一个支持hash、set、list的库包。 你可能会问了,我们为什么不直接选用成熟的基于rocksdb的网络服务封装,而是自己造轮子。  理由很简单,不管是以前的ssdb,现在360 pika都有针对rocksdb做封装,但对于我这种只有本机访问的场景来说,无意是浪费的,另外网络io也是多少是有消耗的。  

再者说,rocksdb封装结构其实很简单的,但是你要考虑搞明白下面几个问题?  


如何保持zset做到高效查询?

空间换时间,尽量热区访问。

如何保证多条命令的原子性?

rocksdb本身是可以保证数据的一致性的,rocksdb是带有 Write Ahead Log预写日志的。 对于一组命令来说,我们可以使用 WriteBatch来包装命令集,rocksdb还是会采用Wal方案避免因服务崩溃丢失数据。

如何控制并发?

rocksdb通过fcntl来控制进程锁,运行初始化时,只有一个进程可以拿到fcntl文件锁。 多个线程倒是可以并发访问,但是并发写写操作会被fifo有序排队执行。 简单说,读读不会阻塞,写写之间会有阻塞的。 这个跟mysql的事务是一回事的。


简单说下,rocksdb的查询过程 ?

每次触发边界memtable会变成Immutable Memtable,接着被写入到最上层的sstable 文件里!每个sstable 都是排序好的,在manifest 里面会记录每个sstable 的key max min区间。  我们要明确一点,多个SStable会存在多个数据,冗余数据,过期数据的。当你去试图读取数据时,那么查询的顺序是从上往下,直到扫完所有的数据块。 为了提高效率,不是每个SSTable都会扫描的,最少每个sstable做了bloom 过滤器,你查询的key也会跟Manifest记录的key区间做对比。

zset作为有序集合,我们最少要实现他的几个命令,zadd添加、scard查询个数、zscore查询分值、zrangebyscore范围查询。当然作为zset的鼻祖,redis有更丰富的命令。 推荐大家把python rocksdb的文档看完,有很多概念性的介绍和实例,比如prefix,iterator,snapshot,merge等。

首先放一个 zset的结构实例,我们可以得出通过 zset_k_xxx_c 得到zcard数据,zset_k_xxx_v_member1拿到zscore的score分值,zset_k_xxx_c_score 拿到 member。


没写完。。。。  下面开始写 python rocksdb的具体方法。。。



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!
{ 2000人qq大群内有各厂大牛,常组织线上分享及沙龙,对高性能及分布式场景感兴趣同学欢迎加入该QQ群 }

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!
暂无相关产品