CAP 定理
Table of Contents
1 CAP 定理
CAP 定理说明在分布式场景中经常遇到的问题,其中 CAP 指分布式系统的三个特性
- C (Consistency) 一致性, 指在任何时候,集群中的节点获取到的状态都是一样的
- A (Availability) 可用性, 指集群中没有宕机的的节点都能正常服务
- P (Partition Tolerance) 分区容错性, 指集群因网络故障或节点故障问题,别切割 成两个(或以上)的不完整的子集群,系统整体能正常运作
针对于上面说的三个特性, CAP 定理的内涵就是说在分布式集群中只能保证两个特性的 存在
2 Partition Tolerance
假如两台节点在不同机器上,如果存入资料的方式是 2PC (Two-Phase Commit), 即所有 节点统一才能提交数据,那么只要 Partition 发生,即任何一个节点宕机,整个系统就 不能运作,可以想象这样的系统实在是太脆弱了,所以一般分布式系统需要保证 P
3 Availability & Consistency
如果保证 P, 那么系统可以容忍 Partition, 根据 CAP 定理需要牺牲 A 或者 C
- 保证 A 的情形: 两个节点虽然彼此不能沟通,但是既然或者就让他们正常服务,这样 其中一半的变化不能传递到另一边,因此可能两边的数据会出现不一致。更糟糕的状 况是会发生 脑裂, 就是 Master 中写入数据,Slave 允许写数据出现时序不一致问 题
- 保证 P 的情形: 为了避免之前的不一致问题,因此必须停掉其中任一个节点
4 数据产品的分类
- CA: 关系型数据库 RDBMS
- Oracle
- MySQL
- Postgresql
- CP: 非关系型数据库和一些中间件
- MongoDB
- HBase
- Redis
- ZooKeeper (偏向于 CP 的设计)
- AP: Cassandra, CouchDB, DynamoDB, Riak
- Cassandra 不保证一致性,高度容错
5 Apache ZooKeeper
5.1 ZK 的 Metadata
ZK 是维持 Cluster 中共同状态的分布式系统,
- ZK 主要维护了一些 Metadata, 用于降低大量更新时同步数据的开销
- ZK 有自己的 HA 和 Consistency 机制,在 Production 环境下只需要维护
2n+1
的 Node 的数据即可保证数据的一致性
5.2 ZK 的几个常见用法
- 共享 Metadata
- ZK 的文件是以树的方式组织,树节点是 znode
- ZK 的节点间有 Notification 机载,在 znode 里的资料更新时需事先通知对该 znode 注册的 Watcher Process
- 监控成员节点的状况 & 维护集群的成员名单
- 有一种 znode 叫做 Ephemeral Node, 用来监控成员的状况。
- Ephemeral Node 跟其它 znode 建立 Session 是连动的
- 若 Session 没有 Heartbeat,Ephemeral Node 会被删除
- 其它 znode 上设定了 watcher, 就会在节点挂掉(即 Session 挂掉后)收到通知
- 协助集群选集 Leader (Master)
- 所有成员对 Master 节点对应的 Ephemeral Node 注册 Watcher
- 当 Master 失效后,会有成员侦测到而启动 Leader Election
5.3 ZK 的 Quorum
- ZK 能保证 Global Order, 因为只有 Leader 能处理写入的需求
- 如果发生 Partition, ZK 任然可以维持服务,因为 ZK 采用了 Quorum 机载,所有 ZK 是偏向于 CA 的系统
- Quorum 是成员数达到最低投票门口的成员集合,Quorum 具有如下属性
- 成员只能是 Leader 或 Follower
- 一个 Quorum 中只有一个 Leader, 其它都是支持改 Leader 的 Follower
- 当集群出现多个 Quorum 时,触发 Leader Election, 拥有半数以上的 Quorum 被称 为 Majority
- 当 Cluster 出现多个 Quorum 时,最多只有 Majority 可以对外进行服务,这样保 证了不会出现不一致的状况
6 Apache Kafka
6.1 Kafka 特点
- 分布式架构,天生容易扩充
- 基于硬盘空间,且避免随机存取
- 因为存储空间大,Queue 里的消息及时消费后,可以不用删掉
- 新加入的 consumer 可以处理过去的消息
- 如果有 Batch-Oriented 的消费者(例如 Hadoop), 可以一次拉取足够大量的资 料,提高 Batch 处理的效率
- 消息的包装轻量级,可压缩
- 因为是直接处理文件,可以利用 OS 的 Page Cache, 避免消耗内存
6.2 Kafka 的基本架构
- 基本上 Kafka 是一个 Broker 的角色,介于 Producer 和 Consumer 之间,Kafka 一般是由多个节点构成的 Cluster
- Kafka 有自己的 Producer API 和 Consumer API
- Producer Client 和 Consumer Client 需要遵循 API 规范进行存取
- Topic 是 Kafka 的一组文件流
- 一个 Topic 可以分成多个 Partition
- 每个 Partition 在不同的节点上
- Producer 需要指定文件写入哪个 Partition
- 通过 Producer API 的一个参数指定 Partition Key
- Producer API 会根据 Hash 方式决定对应的 Partition
- Kafka 可以弹性支持
point-to-point
和pub/sub
两种队列模式- 主要通过一个 Consumer Group 的抽象, Consumer Group 包含多个实体的 Consumer
point-to-point
就是将所有的 Consumer 划分到一个 Consumer Group 中pub/sub
是将不同的 Pub 和 Sub 放在不同的 Consumer Group
- 每个 Consumer 只能同时 bind 到一个 Partition 中
- 一个 Consumer 只会找一个 Partition 来拉取文件
- 一个 Partition 只能被同一 Consumer Group 中的一个 Consumer 消费,这样保 证这个 Partition 对于一个 Consumer Group 来说不会并发取
6.3 Kafka 的限制
- Consumer Group 里的 Consumer 数量不能小于 Partition 数量,否则就会出现 Partition 对不到 Consumer
- 若各个 Consumer 消费速度不均匀,Partition 就会出现失衡
- 由于 Partition 的写入是在 Producer 指定的,所以即使出现失衡也无法通过 Round-robin 来解决
- 综上所述,每个 Partition 实际上可以看成独立的队列
- 每个 Partition 只能保证自己的 Local Order
- 每个 Partition 没有跨 Partition 的 Global Order
- 若有一个 AP 处理跨 Partition 的数据,不能依赖于每个 Partition 的 Local Order, Kafka 天生不适用于 Global Order 的处理
- Kafka 依赖于 ZK 进行 Partition 的 Metadata 存储
6.4 Kafka 的 Replication 机制
- Kafka 的 Replication 是以 Partition 为单位的
- 让 replica 订阅需要追踪的 Partition, 因为这里是 Queue, 直接使用订阅就可 以处理掉 Replication
- 每个 Replica Set 里,只会有一个 Master, 这个 Master 负责所有读写工作,其它 的 Slave 只是备援,所以保证了一致性
- 每个 Replica Set 会维持一个 ISR (In-Sync Replica) 名单
- ISR 中的 Replica 与 Master 较为同步
- 如果 Master 挂掉,在 ISR 中多少挑选出新的 Master
- 写入数据虽然是以 Master 作为窗口,但是要等消息同步到所有 ISR 中,才能算提交
- 未提交的数据不能被 Consumer 消费
6.5 Kafka 的 ACK 确认机制
- ACK 的 ACK 确认只有保证 Message Deliver Semantics
acks=0
生产者在成功写入消息之前不会等待任何来自服务器的响应acks=1
只要集群的 Leader 分区副本接收到了消息,就会向生产者发送一个成功 响应的 ACKacks=all
表示只有所有参与复制的节点 ISR 列表的 Replica 全部收到消息时, 生产者才会接收到来自服务器的响应,此时如果ISR同步副本的个数小于min.insync.replicas
的值,消息不会被写入