1. 简介
Apache Cassandra 是由 Facebook 创立的高度可扩大、高性能的分布式 NoSQL 数据库,能够灵便的在线扩容,满足业务水平扩大的需要。具备可能解决大量数据的分布式架构。数据搁置在具备多个复本因子的不同机器上,以取得高可用性,而无需放心单点故障。
2. 个性
-
分布式和去中心化
Cassandra 是分布式的,这意味着它能够运行在多台机器上,并出现给用户一个统一的整体。你能够释怀地将数据写到集群的任意一台机器上,Cassandra 都会收到数据。去中心化意味着 Cassandra 不会存在单点生效。Cassandra 集群中的所有节点的性能都齐全一样,所以不存在一个非凡的主机作为主节点来承当协调工作。
-
弹性可扩大
节点间应用 gossip 协定通信,不须要重新启动过程,不用批改利用的查问,也无需本人手工从新平衡数据分布。在 Cassandra 里,你只有退出新的计算机,Cassandra 就会主动地发现它并让它开始工作。
-
可调节的一致性
CAP 定律表明,对于任意给定的零碎,只能在一致性(Consistency)、可用性(Availability)以及分区容错性(Partition Tolerance)之间抉择两个。所以 Cassandra 在设计的时候也不得不思考这些问题,因为分区容错性这个是每个分布式系统必须思考的,所以只能在一致性和可用性之间做抉择,而 Cassandra 的利用场景更多的是为了满足可用性,所以咱们只能就义一致性了。然而依据 BASE 实践,咱们其实能够通过就义强一致性取得可用性。
Cassandra 提供了可调节的一致性,容许咱们选定须要的一致性程度与可用性程度,在二者间找到平衡点。因为客户端能够管制在更新达到多少个正本之前,必须阻塞零碎。这是通过设置正本因子(replication factor)来调节与之绝对的一致性级别。
通过正本因子(replication factor),你能够决定筹备就义多少性能来换取一致性。正本因子是你要求更新在集群中流传到的节点数(留神,更新包含所有减少、删除和更新操作)。
客户端每次操作还必须设置一个一致性级别(consistency level)参数,这个参数决定了多少个正本写入胜利才能够认定写操作是胜利的,或者读取过程中读到多少个正本正确就能够认定是读胜利的。这里 Cassandra 把决定一致性水平的权力留给了客户本人。
所以,如果需要的话,你能够设定一致性级别和正本因子相等,从而达到一个较高的一致性程度,不过这样就必须付出同步阻塞操作的代价,只有所有节点都被更新实现能力胜利返回一次更新。而实际上,Cassandra 个别都不会这么来用,起因不言而喻(这样就丢失了可用性指标,影响性能,而且这不是你抉择 Cassandra 的初衷)。而如果一个客户端设置一致性级别低于正本因子的话,即便有节点宕机了,依然能够写胜利。
总体来说,Cassandra 更偏向于 CP,尽管它也能够通过调节一致性程度达到 AP;然而不举荐你这么设置。
-
高可用和容错
从个别架构的角度来看,零碎的可用性是由满足申请的能力来量度的。但计算机可能会有各种各样的故障,从硬件器件故障到网络中断都有可能。任何计算机都可能产生这些状况,所以它们个别都有硬件冗余,并在产生故障事件的状况下会主动响应并进行热切换。对一个须要高可用的零碎,它必须由多台联网的计算机形成,并且运行于其上的软件也必须可能在集群条件下工作,有设施可能辨认节点故障,并将产生故障的节点的性能在残余零碎上进行复原。
Cassandra 就是高可用的。你能够在不中断零碎的状况下替换故障节点,还能够把数据分布到多个数据中心里,从而提供更好的本地拜访性能,并且在某一数据中心产生火灾、洪水等不可抗劫难的时候避免零碎彻底瘫痪。
-
面向行
Cassandra 常常被看做是一种面向列(Column-Oriented)的数据库,这也并不算错。它的数据结构不是关系型的,而是一个多维稠密哈希表。稠密(Sparse)意味着任何一行都可能会有一列或者几列,但每行都不肯定(像关系模型那样)和其余行有一样的列。每行都有一个惟一的键值,用于进行数据拜访。所以,更确切地说,应该把 Cassandra 看做是一个有索引的、面向行的存储系统。
Cassandra 的数据存储构造根本能够看做是一个多维哈希表。这意味着你不用当时准确地决定你的具体数据结构或是你的记录应该蕴含哪些具体字段。这特地适宜处于草创阶段,还在一直减少或批改服务个性的利用。而且也特地适宜利用在麻利开发我的项目中,不用进行长达数月的事后剖析。对于应用 Cassandra 的利用,如果业务发生变化了,只须要在运行中减少或删除某些字段就行了,不会造成服务中断。
当然,这不是说你不须要思考数据。相同,Cassandra 须要你换个角度看数据。在 RDBMS 里,你得首先设计一个残缺的数据模型,而后思考查问形式,而在 Cassandra 里,你能够首先思考如何查问数据,而后提供这些数据就能够了。
-
灵便的模式
Cassandra 的晚期版本反对无模式(schema-free)数据模型,能够动静定义新的列。无模式数据库(如 MongoDB)在拜访大量数据时具备高度可扩展性和高性能的劣势。无模式数据库的次要毛病是难以确定数据的含意和格局,这限度了执行简单查问的能力。
为了解决这些问题,Cassandra 引入了 Cassandra Query Language(CQL),它提供了一种通过相似于结构化查询语言(SQL)的语法来定义模式。最后,CQL 是作为 Cassandra 的另一个接口,并且基于 Apache Thrift 我的项目提供无模式的接口。在这个过渡阶段,术语“模式可选”(Schema-optional)用于形容数据模型,咱们能够应用 CQL 的模式来定义。并且能够通过 Thrift API 实现动静扩大以此增加新的列。在此期间,根底数据存储模型是基于 Bigtable 的。
从 3.0 版本开始,不举荐应用基于 Thrift API 的动静列创立的 API,并且 Cassandra 底层存储曾经从新实现了,以更严密地与 CQL 保持一致。Cassandra 并没有齐全限度动静扩大架构的能力,但它的工作形式却截然不同。CQL 汇合(比方 list、set、尤其是 map)提供了在无结构化的格局外面增加内容的能力,从而能扩大现有的模式。CQL 还提供了扭转列的类型的能力,以反对 JSON 格局的文本的存储。
因而,形容 Cassandra 以后状态的最佳形式可能是它反对灵便的模式。
-
高性能
Cassandra 在设计之初就特地思考了要充分利用多处理器和多核计算机的性能,并思考在散布于多个数据中心的大量这类服务器上运行。它能够统一而且无缝地扩大到数百台机器,存储数 TB 的数据。Cassandra 曾经显示出了高负载下的良好体现,在一个十分一般的工作站上,Cassandra 也能够提供十分高的写吞吐量。而如果你减少更多的服务器,你还能够持续放弃 Cassandra 所有的个性而无需就义性能。
3. 利用场景
-
大规模部署
Cassandra 的很多精美设计都专一于高可用、可调一致性、P2P 协定、无缝扩大等,这些都是 Cassandra 的卖点。这些个性在单节点工作时都是没有意义的,更无奈实现它的全副能力。
然而,单节点关系数据库在很多状况下可能正是咱们须要的。所以你须要做一些评估,思考你的冀望的流量、吞吐需要等。对于评估没有什么硬性的指标和要求。但如果你认为有几种关系型数据库能够很好地应酬你的流量,提供不错的性能,那可能选关系型数据库更好。简略地说,这是因为 RDBMS 更易于在单机上运行,对你来说也更相熟。
然而,如果你认为须要至多几个节点能力撑持你的业务,那 Cassandra 就是个不错的抉择。如果你的利用可能须要数十个节点,那 Cassandra 可能就是个很棒的抉择了。
-
写密集、统计和剖析型工作
考虑一下你的利用的读写比例,Cassandra 是为优异的写吞吐量而特地优化的。
许多晚期应用 Cassandra 的产品都用于存储用户状态更新、社交网络、倡议 / 评估以及利用统计等。这些都是 Cassandra 很好的利用场景,因为这些利用大都是写多于读的,并且更新可能随时产生并伴有突发的峰值。事实上,撑持利用负载须要很高的多客户线程并发写性能,这正是 Cassandra 的次要个性。
-
异地多活
Cassandra 间接反对多地散布的数据存储,Cassandra 能够很容易配置成将数据分布到多个数据中心的存储形式。如果你有一个寰球部署的利用,那么让数据贴近用户会取得不错的性能收益,Cassandra 正适宜这种利用场合。
-
变动的利用
如果你正在“初创阶段”,业务会不断改进,Cassandra 这种灵便的模式的数据模型可能更适宜你。这让你的数据库能更快地跟上业务改良的步调。
4. 数据模型
-
Table & KeySpace
Cassandra 中的 KeySpace 概念和 RDBMS 外面的 DataBase 概念很相似,一个 KeySpace 蕴含多张表,个别将有关联的数据表放到同一个 KeySpace 上面。KeySpace 创立的时候能够指定正本策略,正本因子以及是否启用 CommitLog 机制(相似 HBase 中的 WAL)。
Cassandra 中表的概念和 RDBMS 很相似。不同的是在 Cassandra 中属于同一张表的数据在物理上是散布在不同节点上存储的,同一张表由多个 Partition 组成。
-
Partitions
Cassandra 个别是由多台节点组成的,每台节点负责肯定范畴的,如果应用 Murmur3hash 的时候,每个节点负责的 Token 相似于上面那样:
所以 Token 范畴为 -9223372036854775808 ~ -4611686018427387904 的数据存储在 A 节点;同理,Token 范畴为 -4611686018427387903 ~ -1 之间的数据存储在 B 节点,其余相似;每个 Token 范畴由多个 Partition 形成,每个 Partition 由一行或多行数据组成。
在底层存储中,多个 Partition 组成一个 SSTable(Sorted-String Table)文件。那么同一个 SSTable 文件中的数据数据是如何组织的呢?答案是依照 Partition Key 计算失去的 Token 升序排序的。如果 Partition Key 由多个字段形成那么是将这多个字段拼在一起再计算拼成后字符串的哈希值。
-
Row
Partition 外面蕴含了零个或多个 Row,这些 Row 对应的 Partition Key 是一样的。
Cassandra 通过将列的信息(包含列的名称、类型、表名、keySpace 等信息)保留到对应 SSTable 的 md-X-big-Statistics.db 文件中,相应的行只保留列是否存在的标记信息,这个能够节俭存储空间的占用。HBase 存储数据的时候每个 Cell 都须要保留列名称和列族名称的。
那多个 Cell 之间的程序是如何保障的呢?答案是 依照列名称的字典程序升序排序的。
-
Cell
Cell 就是每列数据的底层实现,Cell 外面蕴含了列的定义信息,比方是否被删除、是否过期、是否设置了工夫戳等。在 Cassandra 外面,Column 有 Simple 和 Complex 之分。non-frozen collection 或 UDT(用户自定义类型)的列是 ComplexColumn(Complex Cell)。
5. 应用注意事项
-
除了二级索引查问,其余所有查问必须指定
分区键
,即第一主键,用于决定数据存储于哪台机器。Cassandra 也反对复合分区键,即多个字段作为分区键,定义时用小括号包起来。
-
第一主键称为分区键
Partition Key
,是用来分区的;除分区键以外的主键称为集群键Clustering Key
(从第二主键开始到最初),用于排序。硬盘中的数据是依照集群键的排列顺序存储的,所以查问时不能跳字段,必须从第二主键开始排序。
- 第一主键 只能用 = 号查问;第二主键往后 反对 = > < >= <=;二级索引列 只反对 = 号。
-
Cassandra 反对创立二级索引,能够创立在除了第一主键 (分区键:partition key) 之外所有的列上;
如果查问条件里,有一个是依据索引查问,那其它非索引非主键字段,能够通过加一个 ALLOW FILTERING 来过滤实现;
- Cassandra 分页查问不反对跳页,每次分页必须从第一页开始,只能下一页 / 上一页的滚动翻页,分页无奈取到总数量和总页码。
-
Cassandra 想要排序功能,在建表时就要指定字段的排序程序,排序字段从第二主键开始,否则数据查问进去是乱序的。
Cassandra 排序须要从第二主键开始,第一主键无奈作为排序字段。在查问时 order by 字段排序程序必须与建表时设置的字段程序统一或齐全相同。
- Cassandra 查问性能较弱,适宜作为存储构造简略的大数据量宽表,做一些简略查问。
Cassandra 不反对 join 和其余简单查问。
6. 架构
Cassandra 集群的架构相似于 redis cluster
,也是用一致性哈希算法来确定数据寄存在那台机器,且也是应用虚构节点的概念。集群节点间也是通过 Gossip 协定来实现无核心架构。
6.1 根本流程
点对点分布式系统,集群中各节点平等,数据分布于集群中各节点,各节点间每秒替换一次信息。
每个节点的 commit log 提交日志
记录写操作日志来确保数据持久性。
数据先被写入MemTable
(内存中的数据结构),待 MemTable 满后数据被写入SSTable
(硬盘的数据文件)。
所有的写内容被主动在集群中 partition 分区
并replicate 复制
。
6.2 库表构造
Cassandra 数据库面向行。用户可连贯至集群的任意节点,通过相似 SQL 的 CQL 查问数据。
集群中,一个利用个别蕴含一个 keyspace
,一个keyspace
中蕴含多个表,keyspace
类比关系型数据库中的database
。
6.3 读写申请
客户端连贯到某一节点发动读或写申请时,该节点充当 客户端利用
与领有相应数据的节点
间的 coordinator 协调者
以依据集群配置确定 环(ring)中的哪个节点
来解决这个申请。
对 Cassandra 的读操作,会依据 primary key
来确定申请被路由到哪个节点下来读取数据,节点上的数据依照 cluster key
排列顺序存储。
6.4 关键词阐明
关键词 | 名词解释 |
---|---|
Gossip |
点对点通信协议,用以 Cassandra 集群中节点间替换地位和状态信息。 |
Partitioner |
决定如何在集群中的节点间散发数据,即在哪个节点搁置数据的第一个 replica。 |
Replica placement strategy |
决定在哪些节点搁置每行数据的其余 replica。Cassandra 在集群中的多个节点存储数据的多份拷贝 (replicas) 来确保牢靠和容错。 |
Snitch |
定义了复制策略用来搁置 replicas 和路由申请所应用的拓扑信息 |
Virtual nodes |
虚构节点, 指定数据与物理节点的所属关系 |
Token Ring |
令牌环 |
6.5 节点间通信 gossip
Cassandra 应用点对点通信协定 gossip 在集群中的节点间替换地位和状态信息。
gossip 过程 每秒
运行一次,与 至少 3 个
其余节点替换信息,这样所有节点能够很快理解集群中的其余节点信息。
gossip 协定的具体表现形式就是配置文件中的 seeds 种子节点。
一个留神点是同一个集群的所有节点的种子节点应该统一,否则如果种子节点不统一, 有时候会呈现集群决裂,即会呈现两个集群,个别先启动种子节点,尽早发现集群中的其余节点。
每个节点都和其余节点替换信息,因为随机和概率,肯定会穷举出集群的所有节点,同时每个节点都会保留集群中的所有其余节点。
这样轻易连到哪一个节点, 都能晓得集群中的所有其余节点。比方 cql 轻易连贯集群的一个节点,都能获取集群所有节点的状态,也就是说任何一个节点对于集群中的节点信息的状态都应该是统一的!
6.6 一致性哈希
图解:key 的范畴是 0 到 2^32 造成一个环,叫做 hash 空间环,即 hash 的值空间。对集群的服务器 (比方 ip 地址) 进行 hash,都能确定其在环空间上的地位。
定位数据拜访到相应服务器的算法:将数据 key 应用雷同的函数 H 计算出哈希值 h,而后依据 h 确定此数据在环上的地位,从此地位沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。
图解:因为一致性哈希算法在服务节点太少时,容易因为节点散布不平均而造成数据歪斜问题,所以引入了虚构节点。
把每台 server 分成 v 个虚构节点,再把所有虚构节点 (n*v) 随机调配到一致性哈希的圆环上,这样所有的用户从本人在 hash 环上的地位顺时针往下取到第一个 vnode 就是本人所属节点。当此节点存在故障时,再顺时针取下一个作为代替节点。
图解:key 通过 hash 会定位到 hash 环上的一个地位,找到下一个 vnode 为数据的第一份存储节点,接下来的两个 vnode 为另外两个正本。
6.7 hash 值空间 &token
下面在计算 key 存在哪个节点上是应用往前游走的形式找到环上的第一个节点,游走是一个计算的过程。
如果可能当时计算好集群中的节点 (vnodes) 在整个 hash 环的值空间,这样对 key 进行 hash 后, 能够看它是落在哪个 hash 值空间上, 而值空间和节点的关系曾经晓得了,所以能够间接定位到 key 落在哪个节点上了。这就是 token
的作用。
在 Cassandra 中,table 的每行由惟一的 primary key
标识,partitioner
分区器依据 hash 函数
计算出primary key 的 token
。Cassandra 根据这个 token 值寻找在集群中搁置对应的行。
7. 读写流程与存储机制
7.1 写流程
当写事件产生时,首先由 Commit Log
捕捉写事件并长久化,保证数据的可靠性。之后数据也会被写入到内存中,叫 Memtable
,当内存满了之后写入数据文件,叫SSTable
,它是 Log-Structured Storage Table 的简称。 如果客户端配置了Consistency Level
是 ONE,意味着只有有一个节点写入胜利,就由协调者节点 (Coordinator) 返回给客户端写入实现。当然这两头有可能会呈现其它节点写入失败的状况,Cassandra 本人会通过 Hinted Handoff 或 Read Repair 或者 Anti-entropy Node Repair 形式保证数据最终一致性。
Cassandra 的存储构造相似 LSM 树
这种构造,不像传统数据个别都应用 B + 树,存储引擎以追加的形式程序写入磁盘间断存储数据,写入是能够并发写入的,不像 B + 树一样须要加锁,写入速度十分高。
Commit Log
记录每次写申请的残缺信息,此时并不会依据主键进行排序,而是程序写入,这样进行磁盘操作时没有随机写导致的磁盘大量寻道操作,对于晋升速度有极大的帮忙。Commit Log
会在 Memtable
中的数据刷入 SSTable
后被革除掉,因而它不会占用太多磁盘空间,Cassandra 的配置时也能够独自设置存储区,这为应用高性能但容量小价格昂贵的 SSD 硬盘存储 Commit Log,应用速度慢但容量大价格十分便宜的传统机械硬盘存储数据的混合布局提供了便当。
写入到 Memtable
时,Cassandra 可能动静地为它分配内存空间,你也能够应用工具本人调整。当达到阀值后,Memtable 中的数据和索引会被放到一个队列中,而后 flush 到磁盘,能够应用 memtableflushqueue_size
参数来指定队列的长度。当进行 flush 时,会进行写申请。也能够应用 nodetool flush 工具手动刷新 数据到磁盘,重启节点之前最好进行此操作,以缩小 Commit Log 回放的工夫。为了刷新数据,会依据 partition key 对 Memtables 进行重排序,而后程序写入磁盘。这个过程是十分快的,因为只蕴含 Commit Log 的追加和程序的磁盘写入。
这里所述的写申请不单指 Insert 操作,Update 操作也是如此,Cassandra 对 Update 操作的解决和传统关系数据库齐全不一样,并不立刻对原有数据进行更新,而是会减少一条新的记录,后续在进行 Compaction
时将数据再进行合并。Delete 操作也同样如此,要删除的数据会先标记为Tombstone
,后续进行 Compaction 时再真正永恒删除。
7.2 读流程
读取数据时,首先查看 Bloom filter
,每一个 SSTable 都有一个 Bloom filter 用来查看partition key
是否在这个 SSTable,这一步在拜访任何磁盘 IO 的后面都会做。Bloom filter 可能误判不会漏判:判断存在, 但实际上可能不存在, 判断不存在, 则肯定不存在,则流程不会拜访这个 SSTable。如果存在,再查看partition key cache
,而后再做如下操作:
- 如果在 cache 中能找到索引,到
compression offset map
中找领有这个数据的数据块,从磁盘上获得压缩数据并返回后果集。 - 如果在 cache 中找不到索引,搜寻
partition summary
(partition index
的样本集)确定索引在磁盘上的近似地位,而后获取索引入口,在 SSTable 上执行一次独自的寻道和一个程序的列读取操作,接下来也是到compression offset map
中找领有这个数据的数据块,从磁盘上获得压缩数据并返回后果集。读取数据时会合并Memtable
中缓存的数据、多个SSTable
中的数据,才返回最终的后果。比方更新用户 email 后,用户名、明码等还在老的 SSTable 中,新的 email 记录到新的 SSTable 中,返回后果时须要读取新老数据并进行合并。
2.0 之后的 Bloom filter
,compression offset map
,partition summary
都不放在 Heap 中了,只有 partition key cache
还放在 Heap 中。Bloom filter 每 billion partitions 增长大概 1 到 2G。partition summary 是 partition index
的样本,你能够通过 index_interval 来配置样本频率。compression offset map 每 TB 增长 1 到 3G。对数据压缩越多,就会有越多个数的压缩块,和越大 compression offset table。
读申请 (Read Request) 分两种,一种是 Rirect Read Request,依据客户端配置的 Consistency Level 读取到数据即可返回客户端后果。一种是 Background Read Repair Request,除了间接申请达到的节点外,会被发送到其它复制节点,用于修复之前写入有问题的节点,保证数据最终一致性。客户端读取时,Coordinator 首先分割 Consistency Level 定义的节点,发送申请到最快响应的复制节点上,返回申请的数据。如果有多个节点被分割,会在内存比拟每个复制节点传过来的数据行,如果不统一选取最近的数据(依据工夫戳)返回给客户端,并在后盾更新过期的复制节点,这个过程被称作 Read Repair。
下图是 Consistency Level 为 ONE 的读取过程,Client 连贯到任意一个节点上,该节点向理论领有该数据的节点发出请求,响应最快的节点数据回到 Coordinator 后,就将数据返回给 Client。如果其它节点数据有问题,Coordinator 会将最新的数据发送有问题的节点上,进行数据的修复。
7.3 数据整顿压缩(Compaction)
更新操作不会立刻更新,这样会导致随机读写磁盘,效率不高,Cassandra 会把数据程序写入到一个新的 SSTable,并打上一个工夫戳以表明数据的新旧。它也不会立马做删除操作,而是用 Tombstone 来标记要删除的数据。Compaction 时,将多个 SSTable 文件中的数据整合到新的 SSTable 文件中,当旧 SSTable 上的读申请一实现,会被立刻删除,空余进去的空间能够从新利用 。尽管 Compcation 没有随机的 IO 拜访,但还是一个重量级的操作,个别在后盾运行,并通过限度它的吞吐量来管制,compactionthroughputmbpersec
参数能够设置,默认是 16M/s。另外,如果 key cache 显示整顿后的数据是热点数据,操作系统会把它放入到 page cache 里,以晋升性能。它的合并的策略有以下两种:
- SizeTieredCompactionStrategy:每次更新不会间接更新原来的数据,这样会造成随机拜访磁盘,性能不高,而是在插入或更新间接写入下一个 sstable,这样是程序写入速度十分快,适宜写敏感的操作。然而,因为数据分布在多个 sstable,读取时须要屡次磁盘寻道,读取的性能不高。为了防止这样状况,会定期在后盾将类似大小的 sstable 进行合并,这个合并速度也会很快,默认状况是 4 个 sstable 会合并一次,合并时如果没有过期的数据要清理掉,会须要一倍的空间,因而最坏状况须要 50% 的闲暇磁盘。
- LeveledCompactionStrategy:创立固定大小默认是 5M 的 sstable,最下面一级为 L0 上面为 L1,上面一层是下面一层的 10 倍大小。这种整顿策略读取十分快,适宜读敏感的状况,最坏只须要 10% 的闲暇磁盘空间。
7.4 数据复制和散发
数据散发和复制通常是一起的,数据用表的模式来组织,用主键来辨认应该存储到哪些节点上,行的 copy 称作replica
。当一个集群被创立时,至多要指定如下几个配置:Virtual Nodes,Partitioner,Replication Strategy,Snitch。
数据复制策略有两种,一种是SimpleStrategy
,适宜一个数据中心的状况,第一份数据放在 Partitioner 确定的节点,前面的放在顺时针找到的节点上,它不思考跨数据中心和机架的复制。另外一种是NetworkTopologyStargegy
,第一份数据和前一种一样,第二份复制的数据放在不同的机架上,每个数据中心能够有不同数据的 replicas。
Partitioner 策略有三种,默认是Murmur3Partitioner
,应用 Murmur Hash。RandomPartitioner,应用 Md5 Hash。ByteOrderedPartitioner 应用数据的字节进行有顺分区。Cassandra 默认应用 MurmurHash,这种有更高的性能。
Snitch 用来确定从哪个数据中心和哪个机架上写入或读取数据, 有如下几种策略:
- DynamicSnitch:监控各节点的执行状况,依据节点执行性能主动调节,大部分状况举荐应用这种配置
- SimpleSnitch:不会思考数据库和机架的状况,当应用 SimpleStategy 策略时思考应用这种状况
- RackInterringSnitch:思考数据库和机架
- PropertyFileSnitch:用 cassandra-topology.properties 文件来自定义
- GossipPropertyFileSnitch: 定义一个本地的数据中心和机架,而后应用 Gossip 协定将这个信息流传到其它节点,对应的配置文件是 cassandra-rockdc.properties
7.5 失败检测和修复
Cassandra 从 Gossip 信息中确认某个节点是否可用,防止客户端申请路由到一个不可用的节点,或者执行比较慢的节点,这个通过 dynamic snitch 能够判断进去。Cassandra 不是设定一个固定值来标记失败的节点,而是通过间断的计算单个节点的网络性能、工作量、以及其它条件来确定一个节点是否失败。节点失败的起因可能是硬件故障或者网络中断等,节点的中断通常是短暂的但有时也会继续比拟久的工夫。节点中断并不意味着这个节点永恒不可用了,因而不会永恒地从网络环中去除,其它节点会定期通过 Gossip 协定探测该节点是否恢复正常。如果想永恒的去除,能够应用 nodetool 手工删除。
当节点从中断中恢复过来后,它会短少最近写入的数据,这部分数据由其它复制节点暂为保留,叫做Hinted Handoff
,能够从这里进行主动复原。但如果节点中断工夫超过 maxhintwindowinms(默认 3 小时)设定的值,这部分数据将会被抛弃,此时须要用 nodetool repair 在所有节点上手工执行数据修复,以保证数据的一致性。
7.6 动静扩大
Cassandra 最后版本是通过一致性 Hash 来实现节点的动静扩大的,这样的益处是每次减少或缩小节点只会影响相邻的节点,但这个会带来一个问题就是造成数据不平均,比方新增时数据都会迁徙到这台机的机器上,缩小时这台机器上的数据又都会迁徙到相邻的机器上,而其它机器都不能分担工作,势必会造成性能问题。从 1.2 版本开始,Cassandra 引入了虚构节点 (Virtual Nodes) 的概念,为每个实在节点调配多个虚构节点(默认是 256),这些节点并不是按 Hash 值顺序排列,而是随机的,这样在新增或缩小一个节点时,会有很多实在的节点参加数据的迁徙,从而实现了负载匀衡。
8. LSM 树
LSM 树 (Log-Structured-Merge-Tree) 的名字往往会给初识者一个谬误的印象,事实上,LSM 树并不像 B + 树、红黑树一样是一颗严格的树状数据结构,它其实是一种存储构造,目前 HBase,LevelDB,RocksDB 这些 NoSQL 存储都是采纳的 LSM 树。
LSM 树的外围特点是利用程序写来进步写性能,但因为分层(此处分层是指的分为内存和文件两局部)的设计会略微升高读性能,然而通过就义小局部读性能换来高性能写,使得 LSM 树成为十分风行的存储构造。
8.1 LSM 树的核心思想
如上图所示,LSM 树有以下三个重要组成部分:
1) MemTable
MemTable 是在 内存 中的数据结构,用于保留最近更新的数据,会依照 Key 有序地组织这些数据,LSM 树对于具体如何组织有序地组织数据并没有明确的数据结构定义。
因为数据临时保留在内存中,内存并不是牢靠存储,如果断电会失落数据,因而通常会通过 WAL(Write-ahead logging,预写式日志)的形式来保证数据的可靠性。
2) Immutable MemTable
当 MemTable 达到肯定大小后,会转化成 Immutable MemTable(不可变的 MemTable)。Immutable MemTable 是将转 MemTable 变为 SSTable 的一种中间状态。写操作由新的 MemTable 解决,在转存过程中不阻塞数据更新操作。
3) SSTable(Sorted String Table)
有序键值对汇合 ,是 LSM 树组在 磁盘 中的数据结构。为了放慢 SSTable 的读取,能够通过建设 key 的索引以及布隆过滤器来放慢 key 的查找。
这里须要关注一个重点,LSM 树 (Log-Structured-Merge-Tree) 正如它的名字一样,LSM 树会将所有的数据插入、批改、删除等操作记录 (留神是操作记录) 保留在内存之中,当此类操作达到肯定的数据量后,再批量地程序写入到磁盘当中。这与 B + 树不同,B+ 树数据的更新会间接在原数据所在处批改对应的值,然而 LSM 数的数据更新是日志式的,当一条数据更新是间接 append 一条更新记录实现的。这样设计的目标就是为了程序写,一直地将 Immutable MemTable flush 到长久化存储即可,而不必去批改之前的 SSTable 中的 key,保障了程序写。
因而当 MemTable 达到肯定大小 flush 到长久化存储变成 SSTable 后,在不同的 SSTable 中,可能存在雷同 Key 的记录,当然最新的那条记录才是精确的。这样设计的尽管大大提高了写性能,但同时也会带来一些问题:
1)冗余存储,对于某个 key,实际上除了最新的那条记录外,其余的记录都是冗余无用的,然而依然占用了存储空间。因而须要进行 Compact 操作 (合并多个 SSTable) 来革除冗余的记录。
2)读取时须要从最新的倒着查问,直到找到某个 key 的记录。最坏状况须要查问完所有的 SSTable,这里能够通过后面提到的索引 / 布隆过滤器来优化查找速度。