转载自http://asyty.iteye.com/blog/1202072数据库
1、Cassandra框架
2、Cassandra数据模型
Colum / Colum Family, SuperColum / SuperColum Family
Colum排序
3、分区策略
Token,Partitioner
bloom-filter,HASH
4、副本存储
5、网络嗅探
6、一致性
Quorum NRW
维护最终一致性
7、存储机制
CommitLog
MenTableapache
图1 Cassandra数组
Cassandra是社交网络理想的数据库,适合于实时事务处理和提供交互型数据。以Amazon的彻底分布式的Dynamo为基础,结合了Google BigTable基于列族(Column Family)的数据模型,P2P去中心化的存储,目前twitter和digg中都有使用。缓存
在CAP特性上,HBase选择了CP,Cassandra更倾向于AP,而在一致性上有所减弱。网络
Cassandra的类Dynamo特性有如下几点:数据结构
l 对称的,P2P架构架构
n 无特殊节点,无单点故障框架
l 基于Gossip的分布式管理dom
l 经过分布式hash表放置数据异步
n 可插拔的分区
n 可插拔的拓扑发现
n 可配置的放置策略
l 可配置的,最终一致性
类BigTable特性:
l 列族数据模型
n 可配置,2级maps,Super Colum Family
l SSTable磁盘存储
n Append-only commit log
n Mentable (buffer and sort)
n 不可修改的SSTable文件
l 集成Hadoop
Colum / Colum Family, SuperColum / SuperColum Family
Column是数据增量最底层(也就是最小)的部分。它是一个包含名称(name)、值(value)和时间戳(timestamp)的三重元组。
下面是一个用JSON格式表示的column:
{ // 这是一个Column
name: "emailAddress",
value: "arin@example.com",
timestamp: 123456789
}
须要注意的是,name和value都是二进制的(技术上指byte[]),而且能够是任意长度。
与HBase相比,除了Colum/Colum Family外,Cassandra还支持SuperColum/SuperColum Family。
SuperColum与Colum的区别就是,标准Column的value是一个“字符串”,而 SuperColumn的value是一个包含多个Column的map,另外一个细微的差异是:SuperColumn没有时间戳。
{ // 这是一个SuperColumn
name: "homeAddress",
// 无限数量的Column
value: {
street: {name: "street", value: "1234 x street", timestamp: 123456789},
city: {name: "city", value: "san francisco", timestamp: 123456789},
zip: {name: "zip", value: "94107", timestamp: 123456789},
}
}
Column Family(CF)是某个特定Key的Colum集合,是一个行结构类型,每一个CF物理上被存放在单独的文件中。从概念上看,CF像数据库中的Table。
SuperColum Family概念上和Column Family(CF)类似,只不过它是Super Colum的集合。
Colum排序
不一样于数据库能够经过Order by定义排序规则,Cassandra取出的数据顺序是老是必定的,数据保存时已经按照定义的规则存放,因此取出来的顺序已经肯定了。另外,Cassandra按照column name而不是column value来进行排序。
Cassandra能够经过Colum Family的CompareWith属性配置Colume值的排序,在SuperColum中,则是经过SuperColum Family的CompareSubcolumnsWith属性配置Colum的排序。
Cassandra提供了如下一些选:BytesType,UTF8Type,LexicalUUIDType,TimeUUIDType,AsciiType, Column name识别成为不一样的类型,以此来达到灵活排序的目的。
Token,Partitioner
Cassandra中,Token是用来分区数据的关键。每一个节点都有一个第一无二的Token,代表该节点分配的数据范围。节点的Token造成一个Token环。例如使用一致性HASH进行分区时,键值对将根据一致性Hash值来判断数据应当属于哪一个Token。
分区策略的不一样,Token的类型和设置原则也有所不一样。 Cassandra (0.6版本)自己支持三种分区策略:
RandomPartitioner:随机分区是一种hash分区策略,使用的Token是大整数型(BigInteger),范围为0~2^127,Cassandra采用了MD5做为hash函数,其结果是128位的整数值(其中一位是符号位,Token取绝对值为结果)。所以极端状况下,一个采用随机分区策略的Cassandra集群的节点能够达到2^127+1个节点。采用随机分区策略的集群没法支持针对Key的范围查询。
OrderPreservingPartitioner:若是要支持针对Key的范围查询,那么能够选择这种有序分区策略。该策略采用的是字符串类型的Token。每一个节点的具体选择须要根据Key的状况来肯定。若是没有指定InitialToken,则系统会使用一个长度为16的随机字符串做为Token,字符串包含大小写字符和数字。
CollatingOrderPreservingPartitioner:和OrderPreservingPartitioner同样是有序分区策略。只是排序的方式不同,采用的是字节型Token,支持设置不一样语言环境的排序方式,代码中默认是en_US。
分区策略和每一个节点的Token(Initial Token)均可以在storage-conf.xml配置文件中设置。
bloom-filter, HASH
Bloom Filter是一种空间效率很高的随机数据结构,本质上就是利用一个位数组来表示一个集合,并能判断一个元素是否属于这个集合。Bloom Filter的这种高效是有偏差的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。所以,Bloom Filter不适合那些“零错误”的应用场合,而在能容忍低错误率的场合下,Bloom Filter经过极少的错误换取了存储空间的极大节省。
原理:位数组 + K个独立hash(y)函数。将位数组中hash函数对应的值的位置设为1,查找时若是发现全部hash函数对应位都是1说明存在,很明显这个过程并不保证查找的结果是彻底正确的。
在Cassandra中,每一个键值对使用1Byte的位数组来实现bloom-filter。
图4 Bloom Filter
Cassandra不像HBase是基于HDFS的分布式存储,它的数据是存在每一个节点的本地文件系统中。
Cassandra有三种副本配置策略:
1) SimpleStrategy (RackUnawareStrategy):
副本不考虑机架的因素,按照Token放置在连续下几个节点。如图3所示,假如副本数为3,属于A节点的数据在B.C两个节点中也放置副本。
2) OldNetworkTopologyStrategy (RackAwareStrategy):
考虑机架的因素,除了基本的数据外,先找一个处于不一样数据中心的点放置一个副本,其他N-2个副本放置在同一数据中心的不一样机架中。
3) NetworkTopologyStrategy (DatacenterShardStrategy):
将M个副本放置到其余的数据中心,将N-M-1的副本放置在同一数据中心的不一样机架中。
网络嗅探主要用来计算不一样host的相对距离,进而告诉Cassandra网络拓扑结构,以便更高效地对用户请求进行路由。主要有三种配置策略:
1) org.apache.cassandra.locator.SimpleSnitch:
将不一样host逻辑上的距离(Cassandra Ring)做为他们之间的相对距离。
2) org.apache.cassandra.locator.RackInferringSnitch:
相对距离是由rack和data center决定的,分别对应ip的第3和第2个八位组。即,若是两个节点的ip的前3个八位组相同,则认为它们在同一个rack(同一个rack中不一样节点,距离相同);若是两个节点的ip的前两个八位组相同,则认为它们在同一个数据中心(同一个data center中不一样节点,距离相同)。
3) org.apache.cassandra.locator.PropertyFileSnitch:
相对距离是由rack和data center决定的,且它们是在配置文件cassandra-topology.properties中设置的。
在一致性上,Cassandra采用了最终一致性,能够根据具体状况来选择一个最佳的折衷,来知足特定操做的需求。Cassandra可让用户指定读/插入/删除操做的一致性级别,一致性级别有多种,如图5所示。
注:一致性级别是由副本数决定,而不是集群的节点数目决定。
Quorum NRW
Quorum协议中,R 表明一次成功的读取操做中最小参与节点数量,W 表明一次成功的写操做中最小参与节点数量。R + W>N ,则会产生相似quorum 的效果。该模型中的读(写)延迟由最慢的 R(W)复制决定,为获得比较小的延迟,R和W有的时候的和比N小。
Quorum协议中,只需W + R > N,就能够保证强一致性。由于读取数据的节点和被同步写入的节点是有重叠的。在一个RDBMS的复制模型中(Master/salve),假如N=2,那么W=2,R=1此时是一种强一致性,可是这样形成的问题就是可用性的减低,由于要想写操做成功,必需要等 2个节点的写操做都完成之后才能够。
在分布式系统中,通常都要有容错性,所以N通常大于3的,此时根据CAP理论,咱们就须要在一致性和分区容错性之间作一平衡,若是要高的一致性,那么就配置N=W,R=1,这个时候可用性就会大大下降。若是想要高的可用性,那么此时就须要放松一致性的要求,此时能够配置W=1,这样使得写操做延迟最低,同时经过异步的机制更新剩余的N-W个节点。
当存储系统保证最终一致性时,存储系统的配置通常是W+R<=N,此时读取和写入操做是不重叠的,不一致性的窗口就依赖于存储系统的异步实现方式,不一致性的窗口大小也就等于从更新开始到全部的节点都异步更新完成之间的时间。
通常来讲,Quorum中比较典型的NRW为(3,2,2)。
维护最终一致性
Cassandra 经过4个技术来维护数据的最终一致性,分别为逆熵(Anti-Entropy),读修复(Read Repair),提示移交(Hinted Handoff)和分布式删除。
1) 逆熵
这是一种备份之间的同步机制。节点之间按期互相检查数据对象的一致性,这里采用的检查不一致的方法是 Merkle Tree;
2) 读修复
客户端读取某个对象的时候,触发对该对象的一致性检查:
读取Key A的数据时,系统会读取Key A的全部数据副本,若是发现有不一致,则进行一致性修复。
若是读一致性要求为ONE,会当即返回离客户端最近的一份数据副本。而后会在后台执行Read Repair。这意味着第一次读取到的数据可能不是最新的数据;若是读一致性要求为QUORUM,则会在读取超过半数的一致性的副本后返回一份副本给客户端,剩余节点的一致性检查和修复则在后台执行;若是读一致性要求高(ALL),则只有Read Repair完成后才能返回一致性的一份数据副本给客户端。可见,该机制有利于减小最终一致的时间窗口。
3) 提示移交
对写操做,若是其中一个目标节点不在线,先将该对象中继到另外一个节点上,中继节点等目标节点上线再把对象给它:
Key A按照规则首要写入节点为N1,而后复制到N2。假如N1宕机,若是写入N2能知足ConsistencyLevel要求,则Key A对应的RowMutation将封装一个带hint信息的头部(包含了目标为N1的信息),而后随机写入一个节点N3,此副本不可读。同时正常复制一份数据到N2,此副本能够提供读。若是写N2不知足写一致性要求,则写会失败。 等到N1恢复后,本来应该写入N1的带hint头的信息将从新写回N1。
4) 分布式删除
单机删除很是简单,只须要把数据直接从磁盘上去掉便可,而对于分布式,则不一样,分布式删除的难点在于:若是某对象的一个备份节点 A 当前不在线,而其余备份节点删除了该对象,那么等 A 再次上线时,它并不知道该数据已被删除,因此会尝试恢复其余备份节点上的这个对象,这使得删除操做无效。Cassandra 的解决方案是:本地并不当即删除一个数据对象,而是给该对象标记一个hint,按期对标记了hint的对象进行垃圾回收。在垃圾回收以前,hint一直存在,这使得其余节点能够有机会由其余几个一致性保证机制获得这个hint。Cassandra 经过将删除操做转化为一个插入操做,巧妙地解决了这个问题。
Cassandra的存储机制借鉴了Bigtable的设计,采用Memtable和SSTable的方式。
CommitLog
和HBase同样,Cassandra在写数据以前,也须要先记录日志,称之为Commit Log,而后数据才会写入到Column Family对应的MemTable中,且MemTable中的数据是按照key排序好的。SSTable一旦完成写入,就不可变动,只能读取。下一次Memtable须要刷新到一个新的SSTable文件中。因此对于Cassandra来讲,能够认为只有顺序写,没有随机写操做。
MenTable
MemTable是一种内存结构,当数据量达到块大小时,将批量flush到磁盘上,存储为SSTable。这种机制,至关于缓存写回机制(Write-back Cache),优点在于将随机IO写变成顺序IO写,下降大量的写操做对于存储系统的压力。因此咱们能够认为Cassandra中只有顺序写操做,没有随机写操做。
SSTable
SSTable是Read Only的,且通常状况下,一个CF会对应多个SSTable,当用户检索数据时,Cassandra使用了Bloom Filter,即经过多个hash函数将key映射到一个位图中,来快速判断这个key属于哪一个SSTable。
为了减小大量SSTable带来的开销,Cassandra会按期进行compaction,简单的说,compaction就是将同一个CF的多个SSTable合并成一个SSTable。在Cassandra中,compaction主要完成的任务是:
1) 垃圾回收: cassandra并不直接删除数据,所以磁盘空间会消耗得愈来愈多,compaction 会把标记为删除的数据真正删除;
2) 合并SSTable:compaction 将多个 SSTable 合并为一个(合并的文件包括索引文件,数据文件,bloom filter文件),以提升读操做的效率;
3) 生成 MerkleTree:在合并的过程当中会生成关于这个 CF 中数据的 MerkleTree,用于与其余存储节点对比以及修复数据。
详细存储数据结构参考 http://www.ibm.com/developerworks/cn/opensource/os-cn-cassandraxu2
单体、模块化
Cassandra和HBase的一个重要区别是, Cassandra在每一个节点是是一个单 Java 进程,而完整的HBase 解决方案却由不一样部分组成:有数据库进程自己,它可能会运行在多个模式;一个配置好的 hadoop HDFS 分布式文件系统,以及一个 Zookeeper 系统来协调不一样的 HBase 进程。