一个存储引擎的设计大致是以下过程:
数据不会直接和磁盘io打交道,因为这样会增加客户端请求的响应时间。通常的做法是在内存中设置一个缓存,然后所有的写入都直接写入了缓存,这样客户端请求不需要磁盘io就可以返回。然后后台再开启一个线程或者进程来负责把缓存的数据刷回磁盘。对于读操作则是先从缓存查看,如果没有再io。
但是这还不够,为了支持事务,需要记录日志,而且是先记录日志才记录数据。至于日志是否需要缓存取决于实现。Mysql innodb是采用的缓存。而Casandra两种都支持,需要配置。innodb的在另一篇中介绍了,这里看看Cassandra。
Commitlog,用于存放日志,每一次更新都是先对commitlog操作,然后才是数据。commitlog有两种策略,一种是每一次更新都记录日志,然后惨记录数据,另一种是批量记录,也就是日志先不记录,达到了一定数量才一起批量记录,这样效率更高,但是可能会丢失数据。
Memtable,这是内存中的一个结构,类似一个hashmap。用于缓存数据。当满足下列条件之一时写入磁盘:
(1)数据条数超过阈值;
(2)数据大小超过阈值;
(3)距离上一次更新时间超过阈值;
commitlog如果是批量方式,那么就会先记录到memtable,之后批量写入commitlog。
memtable是每一个columnfamily对应一个。也就是每一张表对应一个。
SSTable:这是磁盘存储数据的文件。每一个columnfamily都会对应一个SSTable文件。当然一个SSTable实际上是多个文件:Filter,Index,Data和Statistics四种文件。
1.Filter:主要是使用了Bloom 过滤器实现的,用于检测一个key是否存在在这个columnfamily中。使用了filter文件,可以快速判定是否存在一个key。这在大数据中还是很重要的,因为如果按照传统的方式,那么需要按照索引一层一层的找,直到叶子节点才知道是否存在这个key,但是使用过滤器,就可以更快速的判定,这样其实是减少了index文件的负载,同时增加了不存在key的响应时间。
2.Index:如果存在,用于查找一个key在该columnfamily中的位置。这个文件概念上像一个数组,每一个元素是<key, pos>,并不是b tree。这样通常一个index文件会有很多个key,查找效率也不会太高。所以,内存会缓存部分key,按照一定的key间距来存,这样更便于得到key。
3.Data:是存放数据的文件。概念上也是一个数组,<key, index,value>。这里的index有两部分,一个是key的colunm的bloom过滤器,用于查看该key下是否有某一个column。还有一部分是column在该key下的index。所以先用bloom再用index是Cassandra数据存储的一大特色。