Cassandra的存储机制

来源:互联网 发布:MP3音序软件 编辑:程序博客网 时间:2024/05/19 06:50

在2009年兴起的NoSQL运动中,Cassandra是其中重要的一个分布式key-value数据库产品,由Facebook在2008年开源,目前是Apache的顶级项目。最近twitter的一篇声明,表示将从MySQL迁移到Cassandra,更让其声名大振。Cassandra是结合了Google Bigtable的数据模型和Amazon Dynamo高可用框架的一个产品。其数据模型可以参考张瑞的blog。

值得说一下的是Cassandra的存储机制,也是借鉴了Bigtable的设计,采用Memtable和SSTable的方式。和关系数据库一样,Cassandra在写数据之前,也需要先记录日志,称之为commitlog,然后数据才会写入到Column Family对应的Memtable中,并且Memtable中的内容是按照key排序好的。Memtable是一种内存结构,满足一定条件后批量刷新到磁盘上,存储为SSTable。这种机制,相当于缓存写回机制(Write-back Cache),优势在于将随机IO写变成顺序IO写,降低大量的写操作对于存储系统的压力。SSTable一旦完成写入,就不可变更,只能读取。下一次Memtable需要刷新到一个新的SSTable文件中。所以对于Cassandra来说,可以认为只有顺序写,没有随机写操作。

因为SSTable数据不可更新,可能导致同一个Column Family的数据存储在多个SSTable中,这时查询数据时,需要去合并读取Column Family所有的SSTable和Memtable,这样到一个Column Family的数量很大的时候,可能导致查询效率严重下降。因此需要有一种机制能快速定位查询的Key落在哪些SSTable中,而不需要去读取合并所有的SSTable。Cassandra采用的是Bloom Filter算法,通过多个hash函数将key映射到一个位图中,来快速判断这个key属于哪个SSTable。关于Bloom Filter,有兴趣的可以去看看参考文章4,5和6。

为了避免大量SSTable带来的性能影响,Cassandra也提供一种定期将多个SSTable合并成一个新的SSTable的机制,因为每个SSTable中的key都是已经排序好的,因此只需要做一次合并排序就可以完成该任务,代价还是可以接受的。所以在Cassandra的数据存储目录中,可以看到三种类型的文件,格式类似于:

  • Column Family Name-序号-Data.db
  • Column Family Name-序号-Filter.db
  • Column Family Name-序号-index.db

其中Data.db文件是SSTable数据文件,SSTable是Sorted Strings Table的缩写,按照key排序后存储key/value键值字符串。index.db是索引文件,保存的是每个key在数据文件中的偏移位置,而Filter.db则是Bloom Filter算法生产的映射文件。

上面大致介绍了一下Cassandra的存储机制,通过将最新的写操作放在内存中的Memtable,然后定期刷新到磁盘持久化为SSTable,Cassandra将随机写操作转换成了顺序写操作,这可以提升IO性能。

最新写入的脏数据是在内存Memtable表中,因此必须有机制来确保异常情况下,能够将内存中的数据恢复出来。和关系型数据库系统一样,Cassandra也是采用的先写日志再写数据的方式,其日志称之为Commitlog。

和Memtable/SSTable不一样的是,Commitlog是server级别的,不是Column Family级别的。每个Commitlog文件的大小是固定的,称之为一个Commitlog Segment,目前版本(0.5.1)中,这个大小是128MB,这是硬编码在代码(src/java/org/apache/cassandra/db/Commitlog.java)中的。当一个Commitlog文件写满以后,会新建一个的文件。当旧的Commitlog文件不再需要时,会自动清除。

每个Commitlog文件(Segment)都有一个固定大小(大小根据Column Family的数目而定)的CommitlogHeader结构,其中有两个重要的数组,每一个Column Family在这两个数组中都存在一个对应的元素。其中一个是位图数组(BitSet dirty),如果Column Family对应的Memtable中有脏数据,则置为1,否则为0,这在恢复的时候可以指出哪些Column Family是需要利用Commitlog进行恢复的。另外一个是整数数组(int[] lastFlushedAt),保存的是Column Family在上一次Flush时日志的偏移位置,恢复时则可以从这个位置读取Commitlog记录。通过这两个数组结构,Cassandra可以在异常重启服务的时候根据持久化的SSTable和Commitlog重构内存中Memtable的内容,也就是类似Oracle等关系型数据库的实例恢复。

当Memtable flush到磁盘的SStable时,会将所有Commitlog文件的dirty数组对应的位清零,而在Commitlog达到大小限制创建新的文件时,dirty数组会从上一个文件中继承过来。如果一个Commitlog文件的dirty数组全部被清零,则表示这个Commitlog在恢复的时候不再需要,可以被清除。因此,在恢复的时候,所有的磁盘上存在的Commitlog文件都是需要的。

 

参考文章:
[1].http://wiki.apache.org/cassandra/MemtableSSTable
[2].http://wiki.apache.org/cassandra/ArchitectureSSTable
[3].http://blog.csdn.net/jiaomeng/archive/2007/01/27/1495500.aspx
[4].http://www.hellodba.net/2009/04/bloom_filter.html
[5].http://labs.google.com/papers/bigtable.html

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米2a开不开机怎么办 红米4手开不了机怎么办 红米4a开不了机怎么办 魅族手机拨打电话时黑屏怎么办 金立手机拨打电话时黑屏怎么办 红米手机刷机黑屏了怎么办 酷派手机开机黑屏但能嗡嗡响怎么办 酷派手机忘记锁屏密码怎么办 酷派手机锁屏密码忘了怎么办 酷派手机不停的开机关机怎么办 苹果6手机进水了开不了机怎么办 金立手机突然黑屏开不了机怎么办 丢失手机又忘了ID锁怎么办? 小米2按出电话后黑屏怎么办 华为手机桌面拨号键没有了怎么办 华为荣耀5x黑屏后无法关机怎么办 华为手机突然黑屏电池充不了怎么办 华为手机恢复出厂设置后黑屏怎么办 华为荣耀畅玩6a内存不够怎么办 红米note4玩王者荣耀卡怎么办 华为荣耀5a手机被锁怎么办 华为荣耀v8应用锁忘记蜜码怎么办 阿里巴巴一键代销被投诉受假怎么办 登录小米云服务怎么删除密码怎么办 苹果6云空间连接不上怎么办 买家收到淘宝网交易异常通知怎么办 快递把我秒杀的货弄丢了怎么办 手机淘宝退货物流单号填错了怎么办 买家要求退货退款但是不发货怎么办 多给买家寄包裹不接电话怎么办 给买家发货物流单号错了怎么办 淘宝退货退款快递单号填错了怎么办 淘宝不小心点了延迟收货怎么办 淘宝快递地址错了货已经发了怎么办 卖家送运费险买家填错单号怎么办 买家无赖点了延迟收货卖家怎么办 淘宝卖家快递单号填错了怎么办 淘宝店有当天的快递忘记发货怎么办 在美国官网买东西少寄了东西怎么办 闲鱼退货货收了不退钱怎么办 闲鱼退货卖家收到东西不退钱怎么办