Cassandra 简介
Cassandra是云原生和微服务化场景中最好的NoSQL数据库。我信了~
1. Cassandra是什么
高可用性和可扩展的分布式数据库
Apache Cassandra™是一个开源分布式数据,可提供当今最苛刻的应用程序所需的高可用性、高性能和线性可伸缩性。它提供了跨云服务提供商、数据中心和地理位置的操作简便性和轻松的复制,并且可以在混合云环境中每秒处理PB级信息和数千个并发操作。
在Hadoop关联的项目中对Cassandra的解释是:A scalable multi-master database with no single points of failure.
可以看出,高可用性和高可伸缩性是Cassandra最闪亮的特点。没有单点故障。
2. Cassandra vs. MongoDB vs. Couchbase vs. HBase
Apache Cassandra™在高负载下提供了更高的性能,在许多用场景中都超过了它的NoSQL数据库竞争对手。
Apache Cassandra: 高度可伸缩、高性能的分布式数据库,设计用于处理许多商用服务器上的大量数据,提供高可用性,没有单点故障。
Apache HBase: 基于谷歌的BigTable的开源、非关系型、分布式数据库,是用Java编写的。它是Apache Hadoop项目的一部分,在HDFS上运行,为Hadoop提供类似于BigTable的功能。
MongoDB: 跨平台的面向文档的数据库系统,避开了传统的基于表的关系数据库结构,转而使用具有动态模式的类JSON文档,从而使数据在某些类型的应用程序中的集成更加容易和快捷。
Couchbase: 为交互式应用程序优化的分布式NoSQL面向文档的数据库。
3. 架构简介
Cassandra被设计用来处理跨多个节点的大数据工作负载,没有单点故障。Cassandra通过采用跨同构节点的对等分布式系统来解决故障问题,其中数据分布在集群中的所有节点中。每个节点使用点对点gossip通信协议频繁地交换自己和集群中其他节点的状态信息。每个节点上按顺序写入的提交日志被捕获写入活动,以确保数据的持久性。然后,数据被编入索引并写入内存结构,称为memtable,它类似于回写缓存。每次内存结构满了,数据就被写到一个SSTables数据文件的磁盘上。所有写操作都会自动分区并在整个集群中复制。Cassandra定期使用一个称为压缩的进程合并SSTables,丢弃用tombstone标记为要删除的过时数据。为了确保集群中的所有数据保持一致,需要使用各种修复机制。
Cassandra是一个分区的行存储数据库,其中行被组织成具有所需主键的表。Cassandra的体系结构允许任何授权用户连接到任何数据中心中的任何节点,并使用CQL语言访问数据。为了易于使用,CQL使用与SQL类似的语法并处理表数据。通常,集群中的每个应用程序都有一个键空间,由许多不同的表组成。
客户端读或写请求可以发送到集群中的任何节点。当客户端使用请求连接到某个节点时,该节点充当该特定客户端操作的协调器。协调器充当客户端应用程序和拥有所请求数据的节点之间的代理。协调器根据集群的配置方式确定环形中的哪些节点应该获得请求。
3.1. 核心结构
• Node
存储数据的地方。它是Cassandra的基础设施组件
• datacenter
相关节点的集合。数据中心可以是物理数据中心,也可以是虚拟数据中心。不同的工作负载应该使用单独的数据中心,无论是物理的还是虚拟的。复制由数据中心设置。使用单独的数据中心可以防止Cassandra事务受到其他工作负载的影响,并使请求彼此接近以降低延迟。根据复制因子,可以将数据写入多个数据中心。数据中心绝不能跨越物理位置。
• Cluster
一个集群包含一个或多个数据中心。它可以跨越物理位置。
• Commit log
为了持久性,所有数据写入之前都要首先写入提交日志(日志写入优先)。所有数据都刷新到SSTables之后,就可以对其进行归档、删除或回收。
• SSTable(Sorted String Table)
一个SSTable是一个不可变的数据文件,Cassandra定期将memtables写入其中。仅追加SSTables并按顺序存储在磁盘上,并为每个Cassandra表维护SSTables。
• CQL Table
按表行获取的有序列的集合。一张表由多列组成,并且有一个主键。
3.2. 核心组件
• Gossip
一种对等通信协议,用于发现和共享Cassandra集群中其他节点的位置和状态信息。Gossip息也由每个节点本地保存,以便在节点重新启动时立即使用。
• Partitioner
分区程序确定哪个节点将接收一段数据的第一个副本,以及如何跨集群中的其他节点分发其他副本。每一行数据都由一个主键唯一地标识,主键可能与其分区键相同,但也可能包含其他集群列。Partitioner是一个哈希函数,它从一行的主键派生标记。分区程序使用令牌值来确定集群中的哪些节点接收该行的副本。Murmur3Partitioner是新Cassandra集群的默认分区策略,几乎在所有情况下都是新集群的正确选择。
• Replication factor
整个集群中的副本总数。副本因子1表示在一个节点上每一行只有一个副本。副本因子2表示每一行有两个副本,其中每个副本位于不同的节点上。所有的副本都同样重要,没有主副本。你可以为每个数据中心定义副本因子。通常,应该将副本策略设置为大于1,但不超过集群中的节点数。
• Replica placement strategy
Cassandra将数据的副本存储在多个节点上,以确保可靠性和容错能力。副本策略决定将副本放在哪个节点上。数据的第一个副本就是第一个副本,它在任何意义上都不是唯一的。强烈建议使用NetworkTopologyStrategy策略,因为在将来需要扩展时,可以轻松扩展到多个数据中心。创建keyspace时,必须定义副本放置策略和所需的副本数。
• Snitch
snitch将一组机器定义为数据中心和机架(拓扑),副本策略使用这些数据中心和机架放置副本。
在创建集群时,必须配置一个snitch。所有的snitch都使用一个动态的snitch层,该层监视性能并选择最佳副本进行读取。它是默认启用的,建议在大多数部署中使用。在cassandra.yaml配置文件中为每个节点配置动态snitch阈值。
• cassandra.yaml
用于设置集群的初始化属性、表的缓存参数、调优和资源利用率的属性、超时设置、客户端连接、备份和安全性的主要配置文件。
4. 安装
将Cassandra仓库添加到yum源中
新建文件/etc/yum.repos.d/cassandra.repo 并粘贴以下内容:
[cassandra] name=Apache Cassandra baseurl=https://downloads.apache.org/cassandra/redhat/311x/ gpgcheck=1 repo_gpgcheck=1 gpgkey=https://downloads.apache.org/cassandra/KEYS
执行yum install命令:
yum install cassandra
安装完以后就是cassandra服务了
# 启动服务
service cassandra start|status|stop
systemctl start|status|stop cassandra
# 开机启动
chkconfig cassandra on
命令行直接输入cqlsh即可连接到本地cassandra数据库,就像直接输入mysql回车一样
5. 数据分区
Apache Cassandra是一个开源的分布式NoSQL数据库。它提供了具有最终一致语义的分区宽列存储模型。
Cassandra的设计目标:
- 完全多主数据库副本
- 低延迟的全局可用性
- 扩展到商用硬件
- 每增加一个处理器,线性吞吐量就会增加
- 在线负载平衡和集群增长
- 分区key-oriented查询
- 灵活的schema
Apache Cassandra依赖于Amazon Dynamo分布式存储键值系统的多种技术。Dynamo系统的每个节点有三个主要组成部分:
- 在分区数据集上请求协调
- 环的成员和故障检测
- 一个本地存储引擎
Cassandra主要使用前两个集群组件,同时使用基于日志结构合并树(LSM)的存储引擎。特别地,Cassandra使用Dynamo风格:
- 使用一致哈希的数据集分区
- 使用版本化数据和可调一致性的多主(multi-master)复制
- 通过gossip协议进行分布式集群成员和故障检测
- 商用硬件的增量横向扩展
Cassandra以这种方式设计,可以满足大规模(PB级数据)关键业务存储要求。
Cassandra不仅吸收了Dynamo论文中的如何做分布式,如何做副本复制,故障容错等方面成功的经验,又吸取了Google Bigtable中的LSM单机引擎层面精华。理论扎实,工程实现靠谱,所以面世以来,不断受到人们的追捧。
5.1. 数据集分区:一致性哈希
Cassandra通过使用哈希函数对存储在系统中的所有数据进行分区来实现水平可伸缩性。每个分区被复制到多个物理节点,通常跨机架甚至数据中心。
使用一个令牌环的一致性哈希
Cassandra将每个节点映射到连续哈希环上的一个或多个token(令牌),并通过将key哈希到环上然后沿一个方向“遍历”环来决定key应该放在什么位置,类似于Chord算法。一致性哈希与原始数据哈希的主要区别在于,当要哈希到的节点(桶)数量发生变化时,一致哈希只需移动一小部分key。
例如,如果我们有一个8个节点的集群,每个节点都有均匀间隔的token(令牌),并且副本因子(RF)为3,那么要找到一个key的所属节点,我们首先对该key进行哈希以生成一个token(即key的hash),然后沿顺时针方向“walk”(走,遍历),直到遇到三个不同的节点,这时我们找到了该key的所有副本。这个过程可以用下图表示:
每个物理节点有多个令牌
如果你许多物理节点来分散数据,则简单的单令牌一致哈希可以很好地工作。但是如果令牌间隔均匀而物理节点数量很少,此时如果新增一个节点的话就没有令牌可选,以使环保持平衡。Cassandra试图避免令牌不平衡,因为令牌范围不均衡会导致请求负载不均衡。 例如,在前面的示例中,无法在不引起不平衡的情况下添加第九个令牌。
Dynamo论文中提倡使用“虚拟节点”来解决这种不平衡问题。虚拟节点通过将令牌环中的多个令牌分配给每个物理节点来解决该问题。通过允许单个物理节点在环中占据多个位置,我们可以使小型集群看起来更大,因此即使添加单个物理节点,我们也可以使其看起来像我们添加了更多节点。
Cassandra引入了一些术语来处理这些概念:
- Token:dynamo风格的哈希环上的单个位置
- Endpoint:网络上的单个物理IP和端口
- Host ID:单个“物理”节点的唯一标识符,通常存在于一个端点并包含一个或多个令牌
- Virtual Node:哈希环上的一个令牌,由具有相同的主机ID的相同的物理节点拥有
从Tokens到Endpoints的映射形成了Token Map,Cassandra以此来会跟踪哪些环位置映射到哪些物理端点。
例如,在下图中,通过为每个节点分配两个令牌,我们可以仅使用4个物理节点来表示8个节点的集群:
说了这么多,什么意思呢?简单的回顾一下:
token代表哈希环(hash ring)上的一个位置,这这个环上,两个token之间有一个区间范围,这也是key的范围或者理解为哈希值的区间范围。从token到node的映射被称之为Token Map。
上面第一幅图中,描述的是假设你有足够的物理机,再假设副本因子是3,那么1节点对应1个token,这样就是8个节点8个token,形成了如下区间范围:
(t1,t2] -> {n2,n3,n4}
(t2,t3] -> {n3,n4,n5}
(t3,t4] -> {n4,n5,n6}
(t4,t5] -> {n5,n6,n7}
(t5,t6] -> {n6,n7,n8}
(t6,t7] -> {n7,n8,n1}
(t7,t8] -> {n8,n1,n2}
(t8,t1] -> {n1,n2,n3}
假设hash("foo")落在了(t1,t2]区间,那么该key的3个副本放置的位置应该是n2,n3,n4
此时,如果我要新加一个节点n9,就没有token可选了
如果物理机不够怎么办呢?
假设物理机只有4台,但是token的范围区间是固定的,那么4个节点8个token,为了保持平衡,必须1个节点对应2个token
为了保持平衡,只能将虚拟节点均匀分布在物理节点之间,因为是按顺时针方向往前走的,数据最终还是要放到物理节点上的
于是形成了如下区间范围:
(t1,t2] -> {n1,n2,n3}
(t2,t3] -> {n2,n3,n4}
(t3,t4] -> {n3,n4,n1}
(t4,t5] -> {n4,n1,n2}
(t5,t6] -> {n1,n2,n3}
(t6,t7] -> {n2,n3,n4}
(t7,t8] -> {n3,n4,n1}
(t8,t1] -> {n4,n1,n2}
每个物理节点对应两个token的好处:
- 当添加一个新节点时,它从环中的其他节点接收大约相同数量的数据,从而使数据在集群中均匀分布。
- 当删除一个节点时,它丢失的数据与环中的其他成员丢失的数据大致相同,这再次保持了数据在集群中的均匀分布。
- 如果某个节点变得不可用,查询负载(特别是支持令牌的查询负载)将均匀地分布在许多其他节点上。
坏处:
- 每个令牌在令牌环上引入最多2 * (RF - 1)的其他邻居,这意味着在令牌环的一部分失去可用性时,会出现更多的节点故障组合
- 集群范围的维护操作通常会变慢。 例如,随着每个节点令牌数量的增加,集群必须执行的离散修复操作的数量也会增加。
- 跨令牌范围的操作性能可能会受到影响。
6. CAP
根据CAP定理,分布式数据存储不可能同时提供两个以上的以下保证:
- Consistency(一致性): 一致性意味着每次读取都会收到最新的写入或错误输出
- Availability(可用性): 可用性意味着每个请求都会收到响应。不能保证响应中包含最新的写入或数据。
- Partition tolerance(分区容错性): 分区容错是指存储系统对网络分区故障的容错。即使某些消息丢失或延迟,系统仍将继续运行。
CAP定理表明,当使用网络分区时,由于存在分区故障的固有风险,因此必须在一致性和可用性之间进行选择,并且不能同时保证两者。
在基于web的应用程序中,高可用性是的优先级比较高的需求,为此,Cassandra从CAP保证中选择可用性和分区容错性,在一定程度上牺牲数据一致性。
(PS:根据CAP定理,只能同时满足两个,而由网络分区带来的分区错误风险是必然存在的,因此只能在CA中间选一个,Cassandra选择了AP)
Cassandra提供以下保证:
- 高扩展性
- 高可用性
- 持久性
- 写入单个表的最终一致性
- 具有可线性化一致性的轻量级事务
- 保证跨多个表的批量写入完全成功或根本不成功
- 二级索引保证与其本地副本数据一致
高可扩展性
Cassandra是一个高度可扩展的存储系统,可以根据需要添加/删除节点。使用基于gossip的协议,每个节点都保留一个统一且一致的成员列表。
高可用性
Cassandra通过实现容错存储系统来保证数据的高可用性。使用基于gossip的协议进行节点中的故障检测。
持久性
Cassandra通过使用副本来保证数据的持久性。副本是存储在集群中不同节点上的数据的多个拷贝。在多数据中心环境中,副本可以存储在不同的数据中心。如果一个副本由于不可恢复的节点/数据中心故障而丢失,数据不会完全丢失,因为副本仍然可用。
最终一致性
在生产中,Cassandra满足了性能、可靠性、可伸缩性和高可用性的要求,是一个最终一致的存储系统。最终一致性意味着所有更新最终会到达所有副本。相同数据的不同版本可能暂时存在,但最终会协调成一致的状态。最终的一致性是实现高可用性的折衷方案,它涉及一些读写延迟。
轻量级事务
数据必须按顺序读写。Paxos协议实现了轻量级事务,能够使用线性一致性处理并发操作。线性化一致性是与实时约束的顺序一致性,它保证了比较和设置(CAS)事务的事务隔离。使用CAS副本比较数据,并将发现过期的数据设置为最一致的值。使用线性一致性读取允许读取数据的当前状态(可能是未提交的),而不需要进行新的添加或更新。
批量写入
跨多个表进行批处理写操作的保证是,它们最终会成功,或者没有成功。批处理数据首先写入到批处理日志系统数据,当批处理数据成功地存储在集群中时,批处理日志数据将被删除。批处理被复制到另一个节点,以确保在协调节点失败的情况下完成完整的批处理。
二级索引
二级索引是列上的索引,用于查询通常不可查询的表。二级索引在构建时保证与它们的本地副本一致。
7. Docs
https://cassandra.apache.org/download/
https://cassandra.apache.org/doc/latest/architecture/index.html
https://www.datastax.com/products/compare/nosql-performance-benchmarks
https://docs.datastax.com/en/cassandra-oss/3.x/
https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/architecture/archDataDistributeHashing.html
https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlIntro.html
补充:宽表
宽表从字面意义上讲就是字段比较多的数据库表。通常是指业务主题相关的指标、维度、属性关联在一起的一张数据库表。由于把不同的内容都放在同一张表存储,宽表已经不符合三范式的模型设计规范,随之带来的主要坏处就是数据的大量冗余,与之相对应的好处就是查询性能的提高与便捷。(空间换时间)