通常,我们会通过两种手段来扩展我们的数据服务:
- 数据分区:把数据分块放在不同的服务器上
- 数据镜像:让所有的服务器都有相同的数据,提供相当的服务
数据服务的高可用性只能通过第二种方法来完成--数据的冗余存储。但是,加入更多的机器,会让我们的数据服务变得很复杂,尤其是跨服务器的事务处理,也就是跨服务器的数据一致性。
数据一致性,简单说有三种类型:
Weak
弱一致性:当你写入一个新值后,读操作在数据副本上可能读出来,也可能读不出来Eventually
最终一致性:当你写入一个新值后,有可能读不出来,但在某个时间窗口之后保证最终能读出来Strong
强一致性:新的数据一旦写入,在任意副本任意时刻都能读到新值
Master-Slave
读写请求都由
Master
负责。写请求写到
Master
上后,由Master
同步到Slave
上。
从Master
同步到Slave
上,你可以使用异步,也可以使用同步,可以使用Master
来push
,也可以使用Slave
来pull
。 通常来说是Slave
来周期性的pull
,所以,是最终一致性。
Master-Master
一个系统存在两个或多个Master
,每个Master
都提供read-write
服务。这个模型是Master-Slave
的加强版,数据间同步一般是通过Master
间的异步完成,所以是最终一致性。
Two/Three Phase Commit
在分布式系统中,每个节点虽然可以知晓自己在操作时是成功还是失败,却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点的时候,为了保持事务的ACID
特征,需要引入一个座位协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交。
第一阶段
- 协调者会问所有的参与者结点,是否可以执行提交操作。
- 各个参与者开始事务执行的准备工作:如:为资源上锁,预留资源,写
undo/redo log……
- 参与者响应协调者,如果事务的准备工作成功,则回应“可以提交”,否则回应“拒绝提交”。
第二阶段
- 如果所有的参与者都回应“可以提交”,那么,协调者向所有的参与者发送“正式提交”的命令。参与者完成正式提交,并释放所有资源,然后回应“完成”,协调者收集各结点的“完成”回应后结束这个
Global Transaction
。 - 如果有一个参与者回应“拒绝提交”,那么,协调者向所有的参与者发送“回滚操作”,并释放所有资源,然后回应“回滚完成”,协调者收集各结点的“回滚”回应后,取消这个
Global Transaction
。
先尝试再提交
1)牧师分别问新郎和新娘:你是否愿意……不管生老病死……(询问阶段)
2)当新郎和新娘都回答愿意后(锁定一生的资源),牧师就会说:我宣布你们……(事务提交)
一些问题:
- 其中一个是同步阻塞操作,会非常大地影响性能
Timeout
- 如果第一阶段完成后,参与者在第二阶段没有收到决策,那么数据结点会进入不知所措的状态,这个状态会
block
住整个事务
Paxis
算法
任何一个点都可以提出要修改某个数据的提案,是否通过这个提案取决于这个集群中是否有超过半数的结点同意(所以Paxos
算法需要集群中的结点是单数)。