前面已经对Cassandra的一些概念性东西做了介绍,所以就不多说明了,今天主要分享Cassandra 的数据存储结构几种形式--CommitLog、Memtable和SSTable,下面一起看看吧!
Cassandra 的数据存储结构Cassandra 中的数据主要分为三种:
CommitLog:主要记录下客户端提交过来的数据以及操作。这个数据将被持久化到磁盘中,以便数据没有被持久化到磁盘时可以用来恢复。Memtable:用户写的数据在内存中的形式,它的对象结构在后面详细介绍。其实还有另外一种形式是 BinaryMemtable 这个格式目前 Cassandra 并没有使用,这里不再介绍了。SSTable:数据被持久化到磁盘,这又分为 Data、Index 和 Filter 三种数据格式。CommitLog数据格式CommitLog 的数据只有一种,那就是按照一定格式组成 byte组数,写到IO缓冲区中定时的被刷到磁盘中持久化,CommitLog 的持久化方式有两种,一个是 Periodic,一个是 Batch,它们的数据格式都是一样的,只是前者是异步的,后者是同步的,数据被刷到磁盘的频繁度不一样。
CommitLog 的相关的类结构图
它持久化的策略也很简单,就是首先将用户提交的数据所在的对象 RowMutation 序列化成 byte 数组,然后把这个对象和 byte 数组传给 LogRecordAdder 对象,由 LogRecordAdder 对象调用 CommitLogSegment 的 write 方法去完成写操作。
CommitLog 文件数组结构
上图中每个不同的 columnFamily 的 id 都包含在 header 中,这样做的目的是更容易的判断那些数据没有被序列化。
CommitLog 的作用主要是为恢复没有被写到磁盘中的数据。
CommitLog 数据格式的变化过程
Memtable 内存中数据结构Memtable 内存中数据结构比较简单,一个 ColumnFamily 对应一个唯一的 Memtable 对象,所以 Memtable 主要就是维护一个 ConcurrentSkipListMap类型的数据结构,当一个新的 RowMutation 对象加进来时,Memtable 只要看看这个结构是否 <DecoratedKey, ColumnFamily> 集合已经存在,没有的话就加进来,有的话取出这个 Key 对应的 ColumnFamily,再把它们的 Column 合并。
Memtable 相关的类结构图如下:
Memtable 相关的类结构图
Memtable 中的数据会根据配置文件中的相应配置参数刷到本地磁盘中。
其实Cassandra 的写的性能很好,好的原因就是因为 Cassandra 写到数据首先被写到 Memtable 中,而 Memtable 是内存中的数据结构,所以 Cassandra 的写是写内存的。下图基本上描述了一个 key/value 数据是怎么样写到 Cassandra 中的 Memtable 数据结构中的。
数据被写到 Memtable
SSTable 数据格式每添加一条数据到 Memtable 中,程序都会检查一下这个 Memtable 是否已经满足被写到磁盘的条件,如果条件满足这个 Memtable 就会写到磁盘中。先看一下这个过程涉及到的类。相关类图如图 所示:
SSTable 持久化类结构图
Memtable 的条件满足后,它会创建一个 SSTableWriter 对象,然后取出 Memtable 中所有的 <DecoratedKey, ColumnFamily> 集合,将 ColumnFamily 对象的序列化结构写到 DataOutputBuffer 中。接下去 SSTableWriter 根据 DecoratedKey 和 DataOutputBuffer 分别写到 Date、Index 和 Filter 三个文件中。
总结今天主要描述了 Cassandra 中数据的主要的存储格式,包括内存中和磁盘中数据的格式,其实Cassandra的存储机制借鉴了Bigtable的设计,采用Memtable和SSTable的方式。
Cassandra在写数据之前,需要先记录日志,称之为Commit Log,然后数据才会写入到Column Family对应的MemTable中,且MemTable中的数据是按照key排序好的。SSTable一旦完成写入,就不可变更,只能读取。
后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注一下~