UP | HOME

CAP 定理

Table of Contents

1 CAP 定理

CAP 定理说明在分布式场景中经常遇到的问题,其中 CAP 指分布式系统的三个特性

  1. C (Consistency) 一致性, 指在任何时候,集群中的节点获取到的状态都是一样的
  2. A (Availability) 可用性, 指集群中没有宕机的的节点都能正常服务
  3. P (Partition Tolerance) 分区容错性, 指集群因网络故障或节点故障问题,别切割 成两个(或以上)的不完整的子集群,系统整体能正常运作

针对于上面说的三个特性, CAP 定理的内涵就是说在分布式集群中只能保证两个特性的 存在

2 Partition Tolerance

假如两台节点在不同机器上,如果存入资料的方式是 2PC (Two-Phase Commit), 即所有 节点统一才能提交数据,那么只要 Partition 发生,即任何一个节点宕机,整个系统就 不能运作,可以想象这样的系统实在是太脆弱了,所以一般分布式系统需要保证 P

3 Availability & Consistency

如果保证 P, 那么系统可以容忍 Partition, 根据 CAP 定理需要牺牲 A 或者 C

  1. 保证 A 的情形: 两个节点虽然彼此不能沟通,但是既然或者就让他们正常服务,这样 其中一半的变化不能传递到另一边,因此可能两边的数据会出现不一致。更糟糕的状 况是会发生 脑裂, 就是 Master 中写入数据,Slave 允许写数据出现时序不一致问 题
  2. 保证 P 的情形: 为了避免之前的不一致问题,因此必须停掉其中任一个节点

4 数据产品的分类

  1. CA: 关系型数据库 RDBMS
    • Oracle
    • MySQL
    • Postgresql
  2. CP: 非关系型数据库和一些中间件
    • MongoDB
    • HBase
    • Redis
    • ZooKeeper (偏向于 CP 的设计)
  3. AP: Cassandra, CouchDB, DynamoDB, Riak
    • Cassandra 不保证一致性,高度容错

5 Apache ZooKeeper

5.1 ZK 的 Metadata

ZK 是维持 Cluster 中共同状态的分布式系统,

  1. ZK 主要维护了一些 Metadata, 用于降低大量更新时同步数据的开销
  2. ZK 有自己的 HA 和 Consistency 机制,在 Production 环境下只需要维护 2n+1 的 Node 的数据即可保证数据的一致性

5.2 ZK 的几个常见用法

  1. 共享 Metadata
    • ZK 的文件是以树的方式组织,树节点是 znode
    • ZK 的节点间有 Notification 机载,在 znode 里的资料更新时需事先通知对该 znode 注册的 Watcher Process
  2. 监控成员节点的状况 & 维护集群的成员名单
    • 有一种 znode 叫做 Ephemeral Node, 用来监控成员的状况。
    • Ephemeral Node 跟其它 znode 建立 Session 是连动的
    • 若 Session 没有 Heartbeat,Ephemeral Node 会被删除
    • 其它 znode 上设定了 watcher, 就会在节点挂掉(即 Session 挂掉后)收到通知
  3. 协助集群选集 Leader (Master)
    • 所有成员对 Master 节点对应的 Ephemeral Node 注册 Watcher
    • 当 Master 失效后,会有成员侦测到而启动 Leader Election

5.3 ZK 的 Quorum

  1. ZK 能保证 Global Order, 因为只有 Leader 能处理写入的需求
  2. 如果发生 Partition, ZK 任然可以维持服务,因为 ZK 采用了 Quorum 机载,所有 ZK 是偏向于 CA 的系统
  3. Quorum 是成员数达到最低投票门口的成员集合,Quorum 具有如下属性
    • 成员只能是 Leader 或 Follower
    • 一个 Quorum 中只有一个 Leader, 其它都是支持改 Leader 的 Follower
  4. 当集群出现多个 Quorum 时,触发 Leader Election, 拥有半数以上的 Quorum 被称 为 Majority
  5. 当 Cluster 出现多个 Quorum 时,最多只有 Majority 可以对外进行服务,这样保 证了不会出现不一致的状况

6 Apache Kafka

6.1 Kafka 特点

  1. 分布式架构,天生容易扩充
  2. 基于硬盘空间,且避免随机存取
  3. 因为存储空间大,Queue 里的消息及时消费后,可以不用删掉
    • 新加入的 consumer 可以处理过去的消息
    • 如果有 Batch-Oriented 的消费者(例如 Hadoop), 可以一次拉取足够大量的资 料,提高 Batch 处理的效率
  4. 消息的包装轻量级,可压缩
  5. 因为是直接处理文件,可以利用 OS 的 Page Cache, 避免消耗内存

6.2 Kafka 的基本架构

  1. 基本上 Kafka 是一个 Broker 的角色,介于 Producer 和 Consumer 之间,Kafka 一般是由多个节点构成的 Cluster
  2. Kafka 有自己的 Producer API 和 Consumer API
    • Producer Client 和 Consumer Client 需要遵循 API 规范进行存取
  3. Topic 是 Kafka 的一组文件流
    • 一个 Topic 可以分成多个 Partition
    • 每个 Partition 在不同的节点上
    • Producer 需要指定文件写入哪个 Partition
      • 通过 Producer API 的一个参数指定 Partition Key
      • Producer API 会根据 Hash 方式决定对应的 Partition
  4. Kafka 可以弹性支持 point-to-pointpub/sub 两种队列模式
    • 主要通过一个 Consumer Group 的抽象, Consumer Group 包含多个实体的 Consumer
    • point-to-point 就是将所有的 Consumer 划分到一个 Consumer Group 中
    • pub/sub 是将不同的 Pub 和 Sub 放在不同的 Consumer Group
  5. 每个 Consumer 只能同时 bind 到一个 Partition 中
    • 一个 Consumer 只会找一个 Partition 来拉取文件
    • 一个 Partition 只能被同一 Consumer Group 中的一个 Consumer 消费,这样保 证这个 Partition 对于一个 Consumer Group 来说不会并发取

6.3 Kafka 的限制

  1. Consumer Group 里的 Consumer 数量不能小于 Partition 数量,否则就会出现 Partition 对不到 Consumer
  2. 若各个 Consumer 消费速度不均匀,Partition 就会出现失衡
  3. 由于 Partition 的写入是在 Producer 指定的,所以即使出现失衡也无法通过 Round-robin 来解决
  4. 综上所述,每个 Partition 实际上可以看成独立的队列
    • 每个 Partition 只能保证自己的 Local Order
    • 每个 Partition 没有跨 Partition 的 Global Order
  5. 若有一个 AP 处理跨 Partition 的数据,不能依赖于每个 Partition 的 Local Order, Kafka 天生不适用于 Global Order 的处理
  6. Kafka 依赖于 ZK 进行 Partition 的 Metadata 存储

6.4 Kafka 的 Replication 机制

  1. Kafka 的 Replication 是以 Partition 为单位的
    • 让 replica 订阅需要追踪的 Partition, 因为这里是 Queue, 直接使用订阅就可 以处理掉 Replication
  2. 每个 Replica Set 里,只会有一个 Master, 这个 Master 负责所有读写工作,其它 的 Slave 只是备援,所以保证了一致性
  3. 每个 Replica Set 会维持一个 ISR (In-Sync Replica) 名单
    • ISR 中的 Replica 与 Master 较为同步
    • 如果 Master 挂掉,在 ISR 中多少挑选出新的 Master
  4. 写入数据虽然是以 Master 作为窗口,但是要等消息同步到所有 ISR 中,才能算提交
    • 未提交的数据不能被 Consumer 消费

6.5 Kafka 的 ACK 确认机制

  1. ACK 的 ACK 确认只有保证 Message Deliver Semantics
  2. acks=0 生产者在成功写入消息之前不会等待任何来自服务器的响应
  3. acks=1 只要集群的 Leader 分区副本接收到了消息,就会向生产者发送一个成功 响应的 ACK
  4. acks=all 表示只有所有参与复制的节点 ISR 列表的 Replica 全部收到消息时, 生产者才会接收到来自服务器的响应,此时如果ISR同步副本的个数小于 min.insync.replicas 的值,消息不会被写入

Last Updated 2021-07-26 Mon 09:02. Created by Jinghui Hu at 2021-07-25 Sun 17:10.