产生原因:
互联网时代信息量巨大、需要计算能力巨大,不但对用户响应速度要求快,而且吞吐量指标也要向外扩展(既:水平伸缩),于是单节点的服务器无法满足需求,服务节点开始池化。为了有序、合理的分配任务,进行有效的管理,于是开始拆分。分水平拆分和垂直拆分。
- 水平拆分:同一个功能由于单机节点无法满足性能需求,需要扩展成多个节点,多个节点具有一致的功能。一个节点服务一部分的请求量,共同处理大规模高并发的请求。
- 垂直拆分:按功能拆分,把一个复杂的功能拆分成若干个单一简单的元功能,拆分的元功能组合在一起和未拆分前的功能一致。
- 水平和垂直拆分后多个元功能的模块和水平拆分中的多个节点,为了保证他们的信息一致。
强一致性:
- 利用关系型数据库的强一致性原则,升级硬件。拆分时相关业务放到一个数据库分片。如果业务无法满足,则通过记录事务的中间临时状态,最终实现一致性。
最终一致性:
Write-Ahead Log:每一步操作都先写上日志,如果遇到问题,可以读取日志按照步骤恢复,并且继续执行未完成的工作,最后达到一致。
分布式一致性协议:
国际开放标准组织Open Group定义了DTS(分布式事务处理模型),模型中包含4个角色:应用程序、事务管理器、资源管理器、通信资源管理器四部分。事务处理器是统管全局的管理者,资源处理器和通信资源处理器是事务的参与者。
下面介绍两阶段提交协议,三阶段提交协议和阿里巴巴提出的TCC,都是根据DTS的思想演变出来的。
两阶段提交协议:把分布式事务分为两个过程,一个准备阶段,一个提交阶段,准备阶段和提交阶段都是由事务管理器发起。
- 准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,参与者会写redo或者undo日志,锁定资源,然后执行操作,但是不提交。
- 提交阶段:如果每个参与者都明确返回准备成功,也就是预留资源和执行操作成功,协调者向参与者发起提交指令,参与者提交资源变更的事务,然后释放锁定的资源。如果任何一个参与者明确返回准备失败,协调者向参与者发起中止指令,参与者取消已经变更的事务,执行undo日志,释放锁定的资源。
示意图如下:
该协议已知存在的问题:
1、阻塞,对于任何一次指令必须收到明确的响应,才会继续下一步。
2、单点故障,协调者发送一个提交指令后宕机,提交指令仅仅被一个参与者接受,并且参与者接受后也宕机,新选举的协调者无法处理这种情况。
3、脑裂问题。协调者发送提交指令,由的参与者接受到执行了事务,有的参与者没有接受到事务,就没有执行事务,造成多个参与者不一致。
三阶段提交协议:通过超时机制解决了二阶段提交协议的阻塞问题。
- 询问阶段:协调者询问参与者是否可以完成指令,协调者只需要回答是还是不是,而不需要做真正的操作,这个阶段超时导致中止。
- 准备阶段:超时导致成功(超时,协调者和参与者都继续提交事务,默认成功)。
- 提交阶段:
示意图入下:
该协议已知存在的问题:
1、一旦超时,系统仍然会存在不一致,相比两阶段提交协议不会发生阻塞和永远锁定资源。
2、仍然存两阶段提交协议存在的单点问题和脑裂问题。
TCC:
示意图如下:
该协议已知存在的问题:
1、cancel的时候有的参与者接受到指令,有的参与者未接受到指令,最终造成数据不一致。
保证最终一致:
在大规模高并发服务化系统中,如果使用两阶段提交协议和三阶段提交协议,能解决系统间一致性的问题,但实现比较复杂,成本比较高,性能并不能得到保证。相比TCC协议比较容易实现,但是会增加耦合性。
在现实系统中,底线是要保证最终一致性,不需要实现专业、复杂的一致性协议,介绍几种简单、粗暴、有效的方案。
- 查询:每个服务提交一个查询接口,向外输出外部执行操作执行的状态。服务的使用方通过调用查询接口,根据得到的状态决定做不同的操作。实现查询每个服务操作必须要有唯一的流水号,比如流水号,订单号。
- 补偿:有了查询模式,我们能获得具体的操作所处的状态,如果整个操作处于不正常的状态,则需要修改操作中有问题的子操作。为了保证系统的最终一致性而作的操作都叫补偿。根据发起形式分为:自动恢复,通知运营,通知技术。
- 异步确保:对响应时间要求不高的请求通常通过异步的方式处理,处理后通知系统通知使用方。此方案可以对高并发流量削峰,常见的有:电商中的物流,配送,短信和邮件提醒。实践中,将异步任务持久化到数据库,通过定时任务执行未完成的任务,最终每个任务都被成功执行。
- 定期校对。
- 可靠消息模式:为了解耦,利用消息队列。2种模式。
1)、发送消息前,把消息持久化到数据库,并标记为待发送,然后发送消息,如果消息发送成功,将消息改为已发送,定时任务定期从数据库捞出未发送的消息,将消息重新发送。
2)、持久消息的数据库是独立的,并不耦合在业务系统中。发送消息之前,先发送一个预消息给某一个第三方的消息管理器,消息管理器将其持久到数据库,并标记状态为待发送,发送成功后,标记消息为发送成功。定时任务定时从数据库捞取一定时间内未发送的消息,回查业务系统是否要继续发送,根据查询结果来确定消息的状态。
本文完。
参考:https://www.jianshu.com/p/1156151e20c8