《大数据日知录:架构与算法》读书笔记2

Posted by BY KiloMeter on May 2, 2019

第二章 数据复制与一致性

为了提高分布式系统的可用性,一般数据会拷贝多份副本,此外,多份副本还可以提高系统的并发性。

但是数据的多副本会引入数据的一致性问题

数据一致性方面有CAP,BASE,ACID理论,这几个理论在前面的 分布式事务初识已经讲到,这里便不再讲述。

下面主要讲下数据的更新策略,主要有三种:同时更新策略,主从式更新策略和任意节点更新策略

数据更新策略

同时更新

多副本同时更新分为下面两种类型

第一种:不通过任何一致性协议直接同时更新多个副本,这种方式存在一致性问题,如果两个客户端同时发出了updateA和updateB的请求,系统无法确定更新顺序,会出现有些副本先更新A再更新B,另外的副本先更新B再更新A的问题

第二种:通过某些一致性协议预先处理,协议用来确定唯一不同更新操作的执行顺序,由于协议预先处理有处理成本,因此请求时延会增加

主从式更新

这种更新策略适用于存在主副本的情况。这种更新策略的更新操作是先提交到主副本,主副本确定唯一的更新顺序,更新后其他副本进行同步。这种更新策略存在三种类型

第一种:同步方式。主副本等待所有的从副本更新完后才确认更新完毕,这样可以保证数据的强一致性,但是在多副本跨数据中心的情况下,该方式的请求时延较大。

第二种:异步方式。主副本可以在收到更新操作后,不必等待其他从副本更新完毕即可发出确认更新完毕。这种类型存在的问题就是在主副本还未同步到其他副本的情况下,如果主副本发生了崩溃,将会出现数据的一致性问题。因此如果使用该方式,会先将更新操作记录存储到其他可靠的存储系统,防止上述情况发生。

第三种:混合方式。混合上述两种方式,主副本更新完毕后,等待部分从副本更新完步即确认更新完毕,kafka使用的就是该方式来维护多副本的一致性。

任意节点更新

顾名思义,更新操作会发送给任意一个副本,然后有该副本通知其他副本进行同步。

这种方式也有两种情形

第一种:同步通知其他副本,这种情况和主从式更新的第一种类型一样。

第二种:异步通知其他副本,这种情况和同时更新的第二种类型以及主从式更新的第二种类型一样。

一致性协议

两阶段提交协议(2PC)

该协议的主要作用是用于实现数据更新原子性手段

该协议中存在两种实体,一种是协调者(唯一的),主要是对分布式事务进行协调管理,另一种是参与者(多个)

2PC将提交过程分为两个阶段,表决阶段和提交阶段

表决阶段:

协调者向所有参与者发送VOTE_REQUEST消息,当参与者接收到该消息后,向协调者发送VOTE_COMMIT消息回应,告诉协调者自己已经做好提交准备,否则返回VOTE_ABORT消息,告诉协调者目前无法提交事务

提交阶段:

如果协调者接收到所有参与者的VOTE_COMMIT消息,则协调者向所有参与者发送GLOBAL_COMMIT消息,通知参与者进行事务提交。如果没有接收到所有参与者的VOTE_COMMIT,则发送GLOBAL_ABORT,中断此次事务。

具体过程可以看篇 2PC到3PC到Paxos到Raft到ISR

该协议存在三个阻塞态:

1、在事务刚开始的时候,所有参与者在等待协调者的VOTE_COMMIT消息,此时所有的参与者是处于阻塞状态的,

2、在协调者发送完VOTE_COMMIT后等待所有参与者响应时,这个时候的协调者也是处于阻塞的,

3、还有,在最后参与者接收到GLOBAL_COMMIT消息前,参与者也是处于阻塞态的。

会出现阻塞态的系统是一个脆弱的系统,因为有可能出现某些进程的崩溃导致所有的处于阻塞态的对象陷入长时间的等待,系统无法继续向后运行。

虽然可以引入超时机制,在等待一段时间后如果还没有接收到消息则取消事务执行,但是第三种阻塞态无法通过超时机制来解决,因为可能是因为存在网络问题才导致参与者没有接收到GLOBAL_COMMIT消息的,如果通过超时机制粗暴地中止事务,那么可能会出现部分参与者提交了事务而部分参与者没有提交,同样会出现数据一致性问题。

在具体实施2PC时,需要协调者和参与者把操作记录和状态在本地的log上,这样即使发生崩溃了,也能通过log进行恢复

三阶段提交协议(3PC)

3PC用来解决上面的长时间存在阻塞问题,核心是把2PC的提交阶段再细分为预提交阶段和提交阶段

表决阶段没变

预提交阶段:协调者向所有参与者发送preCommit请求,并进入prepared状态。参与者接收到preCommit消息后,会执行事务操作,并将Undo和Redo信息记录到日志中。如果事务执行成功,则向参与者发送ack响应,并等待协调者的最终回应。如果有一个参与者没有响应或者响应提交失败给协调者,协调者会给所有的参与者发送abort消息,并中断事务。如果参与者超出指定时间没有接收到协调者的消息或者接收到abort消息,则中断事务。

提交阶段:协调者接收到所有参与者的ack响应,协调者进入提交状态,并向所有的参与者发送doCommit请求,

参与者接收到doCommit消息后,提交事务,释放资源,并向协调者发送ack,协调者接收到所有参与者的ack后,完成事务。

假如有参与者没有接收到所有参与者的ack,则中断事务。如果参与者在接收到doCommit并执行完事务后,协调者没能接收到所有参与者的ack,则向所有的参与者发送abort请求,中断事务。

3PC在实际中很少使用,因为2PC中出现的问题在实际系统中出现的长时间阻塞情况很少发生,此外,3PC的效率过低。