一致性分为访问一致性和数据一致性. 访问一致性, 是指从观察者的角度, 其访问结果是可预期的. 数据一致性是指从上帝视角看, 多个副本的数据是完全相同的.
Paxos 协议, 这里指的是原始(Basic) Paxos, 其本质是解决访问一致性, 并不解决数据一致性, 它不保证多个副本数据现在是(或者将来是)完全相同的, 它只是在可能不一致的多个副本上提供可预期(一致性)的服务. 这个说法不代表不能使用 Paxos 来保证数据一致性, 而是说, Paxos 的设计目的不在于此.
Raft 同时解决访问一致性和数据一致性. 使用了 Raft 协议的分布式存储系统, 既能提供可预期的数据访问服务, 也能在时间维度上保证多副本数据一致性. 例如, 在系统隔断外部输入的情况下(不再接受写请求), 经过一定的时间(一般从几毫秒到数秒)之后, 使用了 Raft 协议的集群内的多个副本的数据将是完全相同的.
Paxos 协议本身并不能保证系统级的数据的最终一致性, 因为它是基于外界触发的消极全量数据拷贝协议. 如果没有外界输入触发, Paxos 就不拷贝数据, 所以它是消极的. 当需要拷贝时, 它拷贝的是全量的数据, 如果你需要保证整个数据库在多台机器上相同, 你应该拷贝整个数据库, 这显然没有实际意义. 另外, 当拷贝结束时, Paxos 并不保证数据被拷贝到所有节点, 这是第二个消极. 所以, 仅仅使用 Paxos 协议的系统, 在隔断外部输入的情况下, 如果数据不一致, 那么过一百年, 多个副本的数据仍然不一致.
相对比, Raft 的数据拷贝是自动的, 不仅仅依赖外界输入触发, 还依赖时间触发, 所以, Raft 是积极的. 同时, 拷贝结束时, Raft 保证数据被拷贝到了所有节点, 从而实现所有副本是完全相同, 如果达不到这个目的, Raft 就不会停止(不达目的绝不罢休), 这是第二个积极.
前面说过, 你一定要区分就充分和必要. 所以, 我不是说用了 Paxos 就必须是消极的, 而是 Paxos 本身是消极的, 如果你用了 Paxos, 你自己要积极起来, 不能只依赖 Paxos. 例如, 你必须引入日志复制状态机模型, 避免全量拷贝. 另外, 你还必须引入超时重传机制, 主动积极拷贝. 为了优化, 避免读请求也要走完整的 Paxos 流程, 你还要引入 Leader. 天啊, 你在重新发明 Raft!