服务拆分有两种方式,水平和垂直。
水平拆分:单节点无法满足要求,扩展为多节点,每个节点服务一部分请求量,一个dhcp服务器水平扩展的例子:
如图,用户流量上到负载均衡器,应用一致性hash算法负载到每个节点,每个节点就是一对dhcp服务器,包含一个master和一个slave,主备之间灾备通过failover机制。每个节点设置阈值,当可分配的地址池降低到一定比例之下,重新调度地址池资源。
垂直拆分:按照功能拆分,类似协议栈。
一致性问题:拆分后各组件之间数据同步问题,几个经典案例:
1.下订单和扣库存问题:先下订单,扣库存失败,那么超卖;先扣库存,下订单失败,那么少卖
2.同步调用超时:这里同步调用指的是跨网络调用,这是一个分布式系统中无法解决的问题,比如A调用B,超时,那么A不知道是B挂了还是网络通信故障,不知道B是否完成了预设功能
3.异步回调超时:会导致系统间状态不一致,B已经干了,但是A不知道,以为B没干
4.掉单:两个系统协作处理一个流程,互为上下游,一个系统中存在一个请求,另一个系统中不存在,导致掉单
5.系统间状态不一致:即3和4导致的状态
6.缓存和数据库不一致:很常见的场景是http,网页变化主动推送通知更新缓存,实际使用场景中,推送不及时、或者数据库是第三方组件,只能设计成一段时间内从数据库读到的缓存是有效的,那么这段时间内数据项发生变化,导致缓存和数据库不一致
7.本地缓存节点间不一致:每个节点有一个缓存数据的复制,更新缓存是有先后顺序的,更新瞬间,多个节点数据不一致
8.缓存数据结构不一致:某个数据由多个数据元素组成,其中一些失败了
ACID理论:
A:atomicity,原子性
C:consistency,一致性
I:isolation,隔离性
D:durability,永久性
具有ACID特性的数据库是强一致的,例如oracle,mysql,原理是每个事物都是原子的,或者成功或者失败,事物之间是相互隔离的,最终状态是持久落盘的,不存在中间状态。可以用来解决下订单和扣库存问题,将订单表和库存表放到一个关系型数据库中。有时无法放到数据库的一个片上,需要实现最终一致性。
分布式系统CAP原理:
C:consistency,一致性,所有数据备份在同一时刻有同样的值,所有节点在同一时刻读取的数据都是最新的数据副本
A:availability,可用性,好的响应性能,在任何故障模型下,服务都在有限的时间内处理完成并进行相应
P:partition tolerance,分区容忍性,网络上部分消息丢失,系统可以持续工作
CAP原理的核心是,任何分布式系统只能满足以上两点,无法三者兼顾。分布式系统都需要满足分区容忍性,因此需要在一致性和可用性之间进行权衡。若出现了网络分区,那么若A等B处理完成之后再返回,失去了可用性;若不等待直接返回,失去了一致性。
BASE思想:满足CAP原理,牺牲强一致性,保证可用性,通过保证最终一致性尽量满足大多数需求
BA:basically available,基本可用
S:soft state,软状态,状态可以在一段时间内不同步
E:eventually consistent,最终一致,在一定时间窗口内,达到最终一致即可
BASE思想的核心是软状态,也就是临时状态,系统记录每个临时状态,出现故障时从中间状态继续处理或者回滚
BASE思想解决转账问题:A给B转账,分成4个阶段,A准备转账==>A减少==>B增加==>完成转账,系统需要记录每个步骤的状态,一种方法是每个阶段都更新数据库中事物的状态;另一种方法是使用写前日志,每个操作之前写入日志,如果操作遇到问题终止,读取日志并按照步骤进行恢复。第一种方法性能不如第二种,但是第二种方法需要SSD,一般用第一种方法,使用数据库的行级锁。
解决一致性问题的3条经验:
1.向上扩展,保证强一致性
2.水平扩展,将相关数据分到数据库的一个片
3.记录软状态,保证最终一致性
DTS:分布式事物处理模型,包含4种角色:应用程序,事物管理器,资源管理器,通信资源管理器。层级结构如下图:
两阶段提交协议:把分布式事物分成两个阶段,准备阶段和提交阶段,都由事物管理器发起。
准备阶段:协调者向参与者发送指令,参与者评估自己是否可以完成,写前日志、锁定资源、执行操作、返回成功
提交阶段:每个参与者都返回成功,协调者发起提交,参与者提交资源变更的事物,释放锁定的资源,若任何一个参与者失败,协调者发起终止指令,参与者取消已经变更的事物,实行写前日志,释放锁定的资源
两阶段提交协议的问题:
1.锁定资源以保证强一致性,实现复杂、成本高、不灵活
2.阻塞,是同步调用,每一步都会发生阻塞
3.单点故障,协调者发送一个指令后挂了,新选举的协调者无法处理
4.脑裂,有的参与者收到了,有的没收到
三阶段提交协议:在准备阶段之前增加一个询问阶段,协调者发起询问,参与者回答是或者否,不需要真正操作,此阶段超时会导致终止,以解决阻塞问题。需要注意的是,主备阶段之后,协调者和参与者制定的任务中都增加超时,并且超时会继续提交事务并且默认为成功,这是根据经验得来的,倾向于相信超时是通信故障而不是服务器故障。
TCC:将一个任务拆分成3个步骤,try,confirm,cancle,正常流程会先try,没有问题,则confirm,若有问题,执行逆操作cancel。正常流程来说,仍然是一个两阶段协议,但是出现问题时增加了自我修复能力。仍然无法解决脑裂的问题,但是通过补偿将需要人工处理不一致的情况降低到了最少。
保证最终一致性的模式:上面的三种模式都是强一致,过于复杂,实用性角度来说,只要最终一致性就可以了,几种模式:
1.查询模式:服务必须提供查询接口供调用方查询操作执行状态。单笔查询必须提供,批量查询根据需要
2.补偿模式:通过查询发现操作有问题,那么继续执行或者回滚,比如同步调用超时,调用查询接口,若状态是失败或者未知,或者查询也超时了,那么告诉调用方失败,即快速失败策略
3.异步确保模式:把响应时间要求低的流程从主流程中剔除,将异步操作封装入库,通过定时任务捞取
4.定期校对模式:在主流程中的系统之间进行校对通过事后异步批量校对,需要全局唯一ID,调用链
5.可靠消息模式:保持一个不成功队列,定时捞取重传,重传消息需要保证幂等性
6.缓存一致性分析:弱一致性,读时先读缓存再读数据库,写时先写数据库再写缓存
微服务交互模式:
1.同步调用模式
2.接口异步调用模式
3.消息队列异步处理模式
超时问题解决方案:
1.同步超时,两种设计,两状态和三状态,两状态只有成功和失败,三状态加一种处理中
2.异步超时,和同步不同,返回状态是受理和未受理,特殊的是回调超时重传,一般用截断二进制指数退避算法
3.消息队列超时,生产者超时或者调用者超时