列族(column family)

列族相当于mysql中的table;多个列族共享一个WAL文件,但有独立的memtable和sst文件;WAL是预写日志,对rocksdb的写操作,都是记录WAL,之后才会写磁盘,当数据写入磁盘后,才会删除WAL中对应的记录;

列族的删除非常快,为什么?

因为它是顺序写的;可以解决redis中bigkey的删除;

使用rocksdb的哪些特性?

主要使用rocksdb的squence number、snapshot、磁盘顺序写、列族等特性来实现一些应用;可以实现kv数据库、关系型数据库以及Nosql数据库。

pika

数据量很大的时候,redis有以下问题:

  1. 启动的时候,数据从磁盘加载到内存,数据量大的情况下会很慢;50G数据的话,启动时加载到内存需要大约1.5小时;
  2. 主从复制,全量同步,会很慢。

pika就是解决上面的问题;pika实现了redis的协议;pika基于rocksdb,数据都存在磁盘中;50G以上使用pika;pika的效率是redis的80%;pika不支持lua; redis是单线程,pika是多线程;

img

特点

  • 容量大,支持百G数据量的存储
  • 兼容redis,不用修改代码即可平滑从redis迁移到pika
  • 支持主从(slaveof)
  • 完善的运维命令

Blackwidow

pika是基于rocksdb进行存储,需要支持redis的数据类型,包括string,list,set,hash,zset;但是rocksdb本身只支持kv存储,就需要进行一个映射,将redis的数据类型转换成rocksdb的kv进行存储;blackwidow主要就是进行数据转换的;

对于每一种redis的数据类型,使用一个db进行存储;key使用一个列族,value使用一个列族;

img

myrocks

facebook维护的mysql版本,存储引擎使用rocksdb;

myrocks适合用于大数据量业务或者写密集业务。

应用场景

大数据量业务

相比innodb,rocksdb占用更少的存储空间,具备更高的压缩效率,非常适合大数据量的业务;在大数据量的情况下,rocksdb所占空间比innodb少一半以上;如果使用innodb,需要频繁的进行分表分库,使用rocksdb就可以减少分表分库的次数;

img

myrocks为什么占磁盘空间比innodb少?

innodb使用B+树进行存储;一旦离散写,B+树会大量分裂,就会造成每一个页存储不满的情况;距统计innodb存储空间,大约有50%的空间浪费;

myrocks使用rocksdb进行存储,LSM-Tree,顺序存储,所以比innodb节省磁盘空间;

写密集业务

rocksdb采用追加的方式记录DML操作,将随机写变成顺序写;非常适合用在批量插入和更新频繁的业务场景;

myrocks事务实现

myrocks和innodb事务比较

myrocksinnodb
锁级别行锁行锁
隔离级别read commitedrepeatable readread uncommitedread commitedrepeatable readserializable
并发读异常没有解决幻读问题

myrocks没有解决幻读问题;幻读问题需要靠gap锁来解决,myrocks主键支持gap锁,辅助索引不支持gap锁,所以没有解决幻读问题;

mysql的事务,是基于MVCC和锁实现的;myrocks也是类似的;

sequence number

rocksdb中的每一条记录都有一个sequence number,这个sequence number存储在记录的key中;

InternalKey:| User key (string) | sequence number (7 bytes) | value type (1 byte) |

对于同样的User Key记录,在rocksdb中可能存在多条,但它们的sequence number不同;sequence number是实现事务处理的关键,是MVCC的基础。

snapshot

snapshot是rocksdb的快照信息,每个snapshot对应一个sequence number;假设snapshot的sequence number为Sa,那么对于此snapshot来说,只能看到sequence number <= Sa的记录,sequence number > Sa的记录是不可见的。

rocksdb的compact操作会根据已有snapshot信息即全局双向链表来判断哪些记录在compact时可以清理。

判断的大体原则是,从全局双向链表取出最小的snapshot sequence number Sn;如果已删除的老记录的sequence number <= Sn, 那么这些老记录在compact时可以清除。

MVCC

sequence number提供了多版本信息;每次查询时,不需要加锁;而是根据当前的sequence number Sn创建一个snapshot,查询过程中只取小于或等于Sn的最大的sequendce number的记录;查询结束后释放snapshot;这样就实现了MVCC,一致性非锁定读。

rocksdb的MVCC效率要远高于mysql,为什么?

mysql的MVCC是基于undolog的,它存在共享表空间,也是使用B+树存储;假设事务begin之后,有100万次update,那么在对该记录进行备份时,需要执行100万次版本回溯,每次都是基于记录上的undo指针对undo页进行随机读,效率很低。

undolog的,它存在共享表空间,也是使用B+树存储;假设事务begin之后,有100万次update,那么在对该记录进行备份时,需要执行100万次版本回溯,每次都是基于记录上的undo指针对undo页进行随机读,效率很低。

rocksdb对该问题进行了优化,假设原始记录的sequence number为2,该版本即为备份事务可见版本;对于比它更大的版本,在将memtable dump为sst文件,或者对sst文件进行compaction时会删除中间版本,仅保留当前活跃事务可见版本和记录最新的版本;这样提高了快照读的效率,也减少了需占用的存储空间。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐