数据一致性之二:微服务场景下的数据一致性

前文简述了「领域内的数据一致性」,本文来说一说「领域间的数据一致性」。在业务实践中,特别是在微服务场景下,针对不同场景对一致性不同的要求程度,阐述不同的业务模型。

微服务之间的数据同步模型

下面从一致性逐渐增强的角度,阐述了各种同步模型。当然这只是一个大概的评价,像同步和异步的模式有些情况无法对比。

同步请求

业务场景:最普通的微服务之间的请求模型,常用 RPC 实现(含 http 协议)。上游依赖下游的信息(但不是最核心的信息),不处理失败场景。

模型分析

针对 RPC 的特性,有三种可能

  • 请求成功,正常返回(包括业务正确或错误)
  • 发起请求阶段网络异常,下游未处理
  • 返回请求阶段网络异常,下游已处理
  • 有点类似 Unix I/O 模型中的阻塞 I/O

同步请求+重试

业务场景:同步请求失败的情况下(含网络错误或超时),假设是网络抖动引起的,延迟一小段时间后重试。

模型分析

  • 重试后依然失败的可以报警人工处理
  • 重试次数有限制,重试间隔可以用指数递增
  • 多数是读请求,如果是写请求的话需要下游保证幂等性

下图是同步请求及重试的示意图:

image

同步请求+轮询

业务场景:针对整体延迟较高的业务场景,上游服务依赖的下游服务处理时间较长,上游服务执意在「同一个会话」中等待同步数据流程完成。比如某些业务需要等待确认支付流程成功,必须在当前会话中轮询。

模型分析

  • 下游服务需要在接收到请求时做持久化,提高可靠性
  • 下游服务可以在一开始返回一个「业务ID」供后续查询使用
  • 轮询间隔时间可以由下游服务指定
  • 有点类似 Unix I/O 模型中的非阻塞I/O

同步请求+回执

业务场景:和上述的回执模型类似,下游服务处理时间较长,不同的是下游处理完毕后主动通知上游。

模型分析

  • 一般不是用户侧发起的路径
  • 也是最终一致性的体现
  • 有点类似 Unix I/O 模型中的信号驱动I/O

下图是同步请求+轮询及回执的示意图:

image

异步队列

业务场景:消息异步处理模式多应用于非核心链路上负载较高的处理环节中,井且服务的上游不关心下游的处理结果,下游也不需要向上游返回处理结果。

模型分析

  • 我们工程实践中使用 kafka 作为消息队列
  • 实践中 Producer 选择折中的 ack 策略(仅 leader 确认),平衡高并发和高可用
  • 实践中 Consumer 选择 oldest 的接入策略和手动 commit 的确认方式,避免服务中途重启可能导致的消息丢失
  • kafka 的订阅模式,即同一个 topic 对应多消费者组的模式,很适合单上游多下游的服务模式

异步队列+落表(消息投递系统)

业务场景:在异步的场景下,为了更高程度的保证可靠性,在上游服务(生产者这端)加强通知的有效性,即如果消息队列暂时不响应的话,需要对消息落表保存,待后续异步重试。

模型分析

  • 首先对投递方进行失败重试
  • 若干次失败后写数据库,等待异步执行的 worker 扫描数据库后重试
  • 我们在实践中也遇到过数次 kafka 集群异常重启,整个阶段可能持续数分钟

下图是异步队列及落表的示意图:

image

对照我们的 mns 系统。

异步队列+验证(消息确认系统)

业务场景:在前面异步队列+落表的基础上,需要对下游的结果进行验证,以保证业务的可靠性。

模型分析

  • 提前注册业务 topic 对应的下游接口和结果验证方式
  • 经由上文的「消息投递系统」系统,上游服务将数据投递给本系统
  • 本系统与下游服务交互后,通过注册的验证方式判断结果是否正常
  • 错误的结果通过队列重试,失败次数过多后落表报警手动处理
image

对照我们的 notifier 系统。

同步请求+异步队列结合(请求重放系统)

业务场景:类似「同步请求+重试」的场景,上游服务依赖下游的返回数据,但是把这一套重试的可靠性保证独立出来,形成单独的组件,这样有利于减轻业务服务的负担。

模型分析

  • 同步请求失败后,将该请求的参数(含url、param、header等)dump出来
  • 经由上文的「消息投递系统」系统,将上面的 dump 信息投递给本系统
  • 本系统代替业务服务进行不断重试,并将最终结果返回给上游业务服务
  • 失败次数过多后落表报警手动处理
image

对照我们的 replay_system 系统。

同步和异步的对比

《伸缩性和可用性反模式》和《可伸缩性最佳实战》提到:

同步调用在任何软件系统中都是不可避免的,但是我们软件工程师必须明白同步调用给软件系统带来的问题。如果我们将应用程序串接起来,那么系统的可用性就会低于任何一个单一组件的可用性。比如组件 A 同步调用了组件 B,组件 A 的可用性为 99.9%,组件 B 的可用性为 99.9%,那么组件 A 同步调用组件B的可用性就是 99.9% * 99.9% = 99.8%。同步调用使得系统的可用性受到了所有串接组件可用性的影响,因此我们在系统设计的时候应该清楚哪些地方应该同步调用,在不需要同步调用的时候尽量的进行异步的调用。

不要小看可用性从 99.9% 降到 99.8%,落实到一个月上面,不可用的时间增加了43分钟。

同步调用使得组件和组件之间紧密耦合起来,这样就使得要想伸缩应用就需要伸缩所有的组件,这不仅带来使得伸缩的成本增加,而且这种高度耦合性使得伸缩变得更加困难。因此我们需要从应用角度划分出,哪些业务操作是紧密关联的,哪些是可以异步执行的,划分出那些可以异步执行的操作,然后将其进行异步化处理,这样划分的好处就是系统可以应对更大的访问量,消弱访问峰值,比如在同步的时候 A 调用了 B,那么用户能接受响应时间就是 A 处理时间 + B 处理的时间,而采用异步以后,当访问量增大的时候,因为 A 和 B 异步,那么 A 很快返回,用户体会不到延迟,而 B 的处理时间由原来的2秒处理完毕,变为3秒处理完毕,而 B 得处理都是在后台进行的,不会影响到客户响应事件,同时异步也起到了消弱峰值的作用。

所以建议的做法是:

  1. 对于短平快的业务,使用同步模型,直接简单
  2. 对于可靠性要求高的业务,使用异步模型可以提高可靠性
  3. 对于并发压力大的业务,使用异步模型可以提高伸缩性

怎么保证下游幂等性?

  • 用全局唯一ID
  • 用业务状态扭转保证(比如电商里的已支付状态不可能扭转回待支付)

为什么业务补偿型不行?

业务补偿模式是一种纯补偿模式,其设计理念为,业务在调用的时候正常提交,当一个服务失败的时候,所有其依赖的上游服务都进行业务补偿操作(取消操作)。

举个例子,小明从杭州出发,去往美国纽约出差,现在他需要定从杭州去往上海的火车票,以及从上海飞往纽约的飞机票。如果小明成功购买了火车票之后发现那天的飞机票已经售空了,那么与其在上海再多待一天,小明还不如取消去上海的火车票,选择飞往北京再转机纽约,所以小明就取消了去上海的火车票。

这个思路可以延续到 2PC 或者 TCC 模型上面。

参考

原文载于数据一致性之二:微服务场景下的数据一致性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 写在前面 随着微服务架构的推广,越来越多的公司采用微服务架构来构建自己的业务平台。就像前边的文章说的,微服务架构为...
    阿斯蒂芬2阅读 1,748评论 0 7
  • 本文转自微信公众号:架构师之路 服务化有什么好处? 服务化的一个好处就是,不限定服务的提供方使用什么技术选型,能够...
    吃火龙果吐芝麻阅读 219评论 0 1
  • 五月花浓榴火燃,一年蓬静葎藤缠。 风催暑气形无改,雨带寒声亦淡然。 (平水韵) 一年蓬∶蒿草名,著黄蕊白花,花期长...
    沈明东阅读 1,411评论 0 7
  • 在学校自习室的时候偶然翻开了一本杂志,第一次认识了一个叫“大概是井越”的vlogger ,从此开启了我对VLOG深...
    Jiaaabooo阅读 14,113评论 0 3
  • 夏紫(2) 我经常会想,我是一个病孩子。 没人疼,没人爱,没有母亲的孩子像野草一般杂草丛生,自由生长,父亲只管我的...
    猫姐原创阅读 305评论 0 0