概述
单机系统因为业务的变更会使得整个系统越来越复杂,整个代码也越来庞大,基于业务的重新划分或者整个工程的重构会将一个单机系统划分多个分布式的系统。以前能够在一个单机事务的完成的操作(ACID)需要变成多个单机事务,同时需要一个中间协调组件来各个单机事务的一致性。对于强一致性要求分布式业务系统的操作能够同步的返回结果,要么成功(分布式事务提交),要么失败或者多次重试后还是超时(分布式事务回滚)。对于最终一致性要求的分布式业务系统,可以使用异步的方式,生产者(上游系统)先提交本地事务,消费者(下游系统)通过重试保证本地事务生效。
1.幂等和消息重试实现最终一致性
对于要求最终一致性的分布式业务系统(大部分系统都需要),一般场景是上游系统负责生产基础数据,下游系统根据上游系统生产的数据,绑定相关业务。其中要求,对于上游产生的基础数据,必须在下游系统产生正确的绑定业务数据(不能因为下游系统的异常如调用接口超时等造成业务数据的丢失)。
例如:在美团供应链负责生产外卖在线门店数据(上游系统),CRM负责在该外卖门店上绑定相关业务(如在团购部分中找到同样的一家店,产生外卖ID和团购ID的映射关系,这样的关系在美团叫做关联关系)。
方案1:生产者重试,消费者保证接口幂等。
- 生产者负责监控业务方的操作是否完成,如果失败业务方重发消息或者调用重试接口,直到业务方反馈操作完成。
消费者负责实现接口的幂等。并返回给生产者操作成功的消息。
具体过程如下:1)生产者在完成本地事务的同时,在本地记录一条消息记录(同一个事务中)。然后生产者发送MQ消息或者异步的调用接口。2)消费者处理MQ消息或者接口调用请求,并保证操作的幂等性。幂等性的保证可以有两种方式:一种是操作的幂等性如 insert ignore into 消息只会插入一次。另外一种操作是消费者通过记录接口请求或者MQ消息是否被处理过,处理过则返回已经处理成功 3)生产者异步的获取消费者消息的处理结果(通过databus接收消费者数据库的变更或者消费者同步的通过接口或者MQ消息向生产者发送通知)。生产者在接收到处理结果后删除在操作1中记录的本地记录。4)在生产者中添加一个定时任务,按照时间间隔(间隔大于整个分布式事务的时间)的读取没有处理的本地消息记录,重新发起MQ消息或者异步接口或者非事务的接口。
方案2:上游系统保证通知一定发出,下游系统接收通知,并自己保证执行成功。
- 生产数据(上游系统)执行操作并通知消费者(下游系统)。在一个本地事务中保证一定同时成功或者失败。
- 消费者(下游系统)接收MQ消息或者执行请求,并记录消息或者请求记录,在下游系统操作执行成功后,删除消息记录或者请求记录(本地事务可以保证)
具体过程如下:1)上游系统将操作和消息的发送放在一个本地事务中 或者上游的通知接口在下游系统是一个异步执行过程,对上游而言是同步的返回消息请求是否到达 2)下游系统在接收到MQ消息时,可以通过实现重试队列,将处理失败的操作发送到重试队列中,按时间间隔进行重新操作,知道消息处理成功(例如其中有第三方接口超时)。或者在异步流程中先记录消息,再在一个本地事务中同时的进行数据操作和本地记录的删除。
PS:上述的两种方案适用于异步调用的系统,其对于数据只要求最终一致性,并且允许系统存在一段时间的数据不一致的情况,并且不会出现上游数据的回滚操作。
方案3:同步类型的分布式事务。该类型的分布式事务,可能会出现回滚操作。
例如:1)一个订单系统,需要在A系统下单,订单处于I初始状态 2)在B系统支付,当支付成功,更新A系统订单I为已经支付状态 3)通知C系统进行发货,发货成功后将A系统订单I改为已发货状态。
- 数据一致性问题1:订单支付成功后,修改订单的初始状态到已经支付状态。这里可能会出现因为调用支付功能成功,用户扣取金额,但是返回超时。解决方案同上,支付功能接口实现根据订单号的幂等,订单系统反复调用直到获取到支付结果为止。(可用性损失:用户支付成功,但是订单系统有一段时间还是初始化状态)
- 数据一致性问题2:订单变为已支付状态调用,调用库存系统进行发货。实现思路同上,库存系统实现幂等,订单系统调用库存接口直到返回结果为止。但是如果遇到库存为0的情况,则订单系统需要调用支付系统的回滚接口给用户退款。(可用性损失:对于一些特价商品会对用户造成一些不好影响的,因为用户不在关心的是退款问题,而是特价商品)。
- 可用性问题:在互联网系统中,可用性是一个十分重要的标准,因此大部分的系统都不会采用先付款,再减库存的方式。一般是先减库存(或者锁定库存),然后在付款的方式。该种方式能够更大的保证用户的体验,缺点就是系统的并发性更低,因为大部分的用户都会卡在减库存或者锁定库存的操作上。同时会出现部分用户锁定或者占用库存但是不付款的情况,这样对另一部分用户会有影响。例如:火车售票就是采用的下订单->减库存->再付款的方式。因为火车票和金额相比,用户更加在意的是火车票这样的紧俏商品。
2.两段提交的分布式事务框架
两段提交的核心是,在预提交阶段会先进行预操作,对一些数据进行加锁,并记录数据的处理结果到事务日志。在事务的正式提交的阶段,会检查执行结果进行提交,该阶段会有两种操作,一种是事务提交成功,返回成功。另外一种是中断操作。最后分布式框架根据各个分布式的事务处理结果,最终决定是提交事务还是发起回滚操作。
具体的分布式架构可以参考支付宝的实现思路:https://wenku.baidu.com/view/3392dabff5335a8103d22092.html
最后
以上就是体贴诺言为你收集整理的分布式业务系统的一致性的全部内容,希望文章能够帮你解决分布式业务系统的一致性所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复