谈谈如何解决业务代码里的分布式事务一致性问题

316 阅读5分钟
原文链接: www.toutiao.com

微服务架构解决了很多问题,但是同时引入了很多问题。本文要探讨的是如何解决下面这几个问题。

有大量的同步 RPC 依赖,如何保证自身的可靠性?

依赖的微服务调用失败了,我应该失败,还是成功。依赖很多外部服务之后,自身如何保障稳定性。如果所有依赖的服务成功,我才算成功,自身的稳定性就堪忧了。

谈谈如何解决业务代码里的分布式事务一致性问题

RPC 调用失败,降级处理之后如何保证数据可修复?

如果调用失败时,选择跳过。那么因此产生的数据不一致性问题如何修复?平时毛毛雨,可以忽略。但是大故障之后,人工还是要来擦屁股的,这个成本就特别高。使用消息队列的最大的意义是在让消息可以在故障的时候堆积起来,等故障恢复了再慢慢来处理,减少人工介入的成本。

谈谈如何解决业务代码里的分布式事务一致性问题

消息队列是一个RPC主流程的旁路流程,怎么保证可靠性?

依赖消息队列做系统解耦的时候,怎么确保消息自身是可靠入队列的?消息是否需要先可靠写入队列,然后再提交数据库事务?如果消息必须先写入队列,比如 kafka。但是 kafka 挂了怎么办?那我在线业务岂不被离线的队列给连累了?

谈谈如何解决业务代码里的分布式事务一致性问题

消息队列怎么保持与数据库的事务一致?

如果消息是先写入队列,然后数据库提交事务。那么就会有因为并发修改的情况下,数据库提交失败,但是消息已经写入到队列的情况。如果队列后面挂了奖励等业务流程,这个时候就会导致错发,或者要求奖励那边去再查一遍数据库的状态。但是如果先提交数据库事务,后写入队列,又无法严格保证队列里的消息是没有丢失的。

谈谈如何解决业务代码里的分布式事务一致性问题

这些问题是所有混用了 RPC 和异步队列的业务都会遇到的普遍问题。这里我给一个提案来解决以上的所有问题。

同步转异步,解决稳定性问题

在平时的时候,都是 RPC 同步调用。如果调用失败了,则自动把同步调用降级为异步的。消息此时进入队列,然后异步被重试。所以处理下游依赖就变成了三种可能性

  • 完全强依赖,下游不能挂
  • 因为我的返回值依赖了某个下游的处理结果,我必须同步调用它。但是不是强依赖,可降级。降级时不返回这部分的数据。同步调用降级时转为异步的。
  • 完全异步化。下游服务只是消费我写入的队列,我不与之直接RPC通信

把消息队列放入到主流程

如果要把重要的业务逻辑挂在消息队列后面。必须要保证消息队列里的数据的完整性,不能有丢失的情况。所以不能是把消息队列的写入作为一个旁路的逻辑。如果消息队列写入失败或者超时,都应该直接返回错误,而不是允许继续执行。

Kafka 的稳定性和延迟时常不能满足在线服务的需要。比如如果要可靠写入三副本,Kafka 需要等待多个 broker 的应答,这个延迟可能会有比较大的波动。在无法及时写入的情况,我们需要使用本地文件充当一个缓冲。

实际上是通过引入本地文件队列结合远程分布式队列构成一个可用性更高,延迟更低的组合队列方案。这个本地的队列如果能封装到一个 Kafka 的 Agent 作为本地写入的代理,那是最理想的实现方式。

谈谈如何解决业务代码里的分布式事务一致性问题

保障分布式事务一致性

前面我们说了要用队列,要依靠队列。但是并没有解决数据库和消息队列是两个独立的事务,没法保证最终一致性的问题。

谈谈如何解决业务代码里的分布式事务一致性问题

这么一串流程,如果RPC1,RPC2成功了,但是流程被中断了(比如停电)。那么RPC3就不会被执行,数据就不一致了。这里的RPC1可能是数据库操作,RPC3可能是消息队列的入队列的调用,都是一回事。

这个问题的解决办法是把责任推给第三方。

谈谈如何解决业务代码里的分布式事务一致性问题

我们需要一个延迟队列,在业务入口的时候挂一个延迟job,然后执行完了取消它。如果没有执行完,则延迟队列负责去触发这个延迟任务,把整个业务流程重复执行一遍。

这样我们就可以保证任意rpc操作流程的最终一致性了。而入kafka消息队列作为RPC操作的一种,自然也是可以得到保证的了。

总结

前面给了三个独立的技术方案

  • 使用同步转异步的方案,提高同步 RPC 的可用性,同时提高数据一致性。
  • 引入本地队列作为兜底,提高消息队列的总体可用性,以及降低延迟。
  • 通过引入延迟队列做监管方,保证一串RPC调用可以最终被执行完

我们只需要把这三个独立的方案结合到一起,就可以把队列技术应用到纯 RPC 同步组合的微服务集群里,用于提高可用性和数据的一致性。同时可以保证这份消息数据是可靠的,从而给其他的业务逻辑把自己放在队列后面,建立了前提条件。

Java知音,专注于Java实用文章推送,不容错过!

来源:https://zhuanlan.zhihu.com/p/25346771