43

微服务的灾难-最终一致

 5 years ago
source link: http://xargin.com/disaster-of-microservice-evconst/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

现在的架构师总喜欢把最终一致挂在嘴上,好像最终一致是解决分布式场景下数据一致问题的金科玉律。事实上又怎么样呢?

事实上的这些人嘴里的最终一致,往往都是最终不一致。在多个系统之间进行数据传递时,无非通过 RPC 或者异步消息。RPC 能保证一致性么?当 B 系统需要 A 系统提供数据时,想要达到一致的效果,那么在 A call B 时发生失败,那么必须让 A 中的逻辑终止。这样才能够使 B 中的状态或数据与 A 中的完全一致。这样实际上需要让 A 和 B 成为生死共同体,B 挂了,那 A 也得挂。可能么?在中大型规模的互联网公司的业务系统中,其下游系统往往有几十个,因此实际的场景是 A call B -> A call C -> A call D .... -> A call Z。这种情况下,你想让所有系统中的状态都一致,那是不可能的。

有的架构师又拿出 saga pattern 来说事,我如果有写数据的逻辑,那么我自然会有一套回滚逻辑,只要在中间发生错误,那么我就对之前的所有调用执行回滚逻辑即可。然而回滚是需要开发量的。我所有下游系统那都得支持回滚才行啊,你觉得做得到么? saga pattern 的异常处理就更扯蛋了:回滚过程中发生失败的话,那需要人工介入,人肉处理。显然人肉是处理不过来的,机房网络抖动实在太正常了,可能一天两天的就会有一次,每次抖动都造成 bad case,研发人员不用干别的事情了,都去处理 bad case 好了。

当然上面这种情况比较极端,一般公司内有靠谱的 MQ 方案的话,会选用 MQ 对这种数据同步的场景进行解耦。之前我做的一些总结也都提到过,只要往 MQ 发一条消息,在字段上尽量满足下游系统,那么我就不用挨个儿去调用他们了,可以很好地进行解耦。从设计的角度上来讲,这确实是比较好的解耦形式。但是你要考虑,逻辑执行和消息发送这两步操作并不具备原子性,除非 MQ 支持事务消息,我才能完成两个操作同时成功或者失败,何况逻辑执行内部可能还有更多的子操作,这件事情远没有打打嘴炮那么简单。

也有的公司会将发送失败的消息进行落盘,比如落进 MySQL 或者写入到磁盘,在发送失败之后,由后台线程在合适的时间进行重发,以让消息能够最终发出。一些简单的场景,这样确实算是解决了问题。如果下游对于消息本身有顺序要求呢?比如订单的状态流转,如果顺序错了,那状态机最终的状态都错乱了。又是一个麻烦的问题。

在当前的开发环境下,想要达到最终一致的效果需要上下游同时进行很多工作,例如上面说的异步消息的场景,上游至少需要做失败落盘和后台发送。而下游需要在状态机的正常状态流转之外,处理各种麻烦的乱序问题。这种乱序处理基本和业务是强相关的,并没有通用方案。即使是同一套状态机,针对不同的业务场景可能还需要定制不相同的业务逻辑。

除了网络抖动,数据不一致的问题可能还会因为模块上线导致。有些公司(比如我司)为了简单 MQ 的消费逻辑,提供了一套由 MQ 平台消费,然后通过 http post 来将消息发送给业务系统的逻辑,降低了业务系统的消息消费开发成本(这样就不用使用 MQ 的 client)了。这种情况下如果模块发生上线的话,即使在 MQ 平台侧有 post 重试,但在模块上线时,还是有概率发生消息丢失。如果有一些状态机流转强依赖于这些消息,那也会造成一部分 bad case。而且这种 bad case 查起来真是没什么意思。之后的数据修复也基本只能靠研发人员自行修复。

这种恶劣的场景下,也有一些人想到了一种方法,我在业务模块中插入多个桩,只要可以每过一段时间触发状态的全量更新,那么我就找一个其它模块来持续地刷新我系统中的数据状态。从而达到“最终一致”。只要这些最终一致的数据没有暴露给用户,没人看得见,那就是最终一致。倒确实是个可用的方案。但架构师们在吹牛逼的时候,对于这种恶心的逻辑一定是绝口不提的。

大多数公司的架构师嘴里的最终一致,依靠的都是人肉而非技术。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK