专栏首页Coder的技术之路高并发消息队列补充篇:在所依赖存储不授信的场景下实现柔性事务降级

高并发消息队列补充篇:在所依赖存储不授信的场景下实现柔性事务降级

文章出自本人公号,欢迎关注,后台提供高并发系列历史文章整理版下载

Part1新公司做设计的些许不适应

在大厂和小厂做研发到底有啥不一样?其他好的坏的方方面面没法细说,咱主要还得说技术方面。

本来大部分的架构体系和思维都是在大厂构建的,到了小厂之后发现,起止是不适用,简直就是不适用(夸大了,?)。其实就本人理解主要是在底层的基础能力的支持程度上有所差异。

很多时候,在大厂待惯了的同学,或者一直在大厂待着的同学,思维惯性是不可避免的,感觉某些能力是理所应当的时候,往往实际情况是无法百分之百契合的。

所以,这种情况下,更要求我们有更强的细节把控能力,在系统设计和实施之前,要把所有涉及到的外部服务、底层支撑程度全都考虑进去,并一一应证,以做到万无一失。

本文阐述一个本人真实的采坑经历,希望帮大家加深对系统设计把控能力的重视。

Part2基础服务支持不到位的坑

2.1项目背景和整理设计思路

项目背景其实还是我们的数据一致性保证长事务引擎。

技术架构的设计思路在《分布式事务从入门到放弃(二)--详述DT引擎一致性原理及设计》一文中已有详述。这里就简单叙述下。(已经被我说了好几次,没办法,只有自己从0 到 1搭起来的,才理解的最深刻)

整体架构如下:

  • 通过状态机来组织和支持多种不同的业务流
  • 通过将外部服务节点化来抽象和规范化参与者的服务
  • 通过节点的异常捕获来感知参与方的执行结果
  • 通过实时或异步的恢复机制,实现柔性事务·

2.2不可缺少的强依赖--存储

想要业务请求保证最终一致,不可能是没有存储参与的一锤子买卖,因为还要考虑本身服务器的抖动,业务上的异步要求等等。所以,存储是一个不可缺少的依赖,如下图所示:

存储服务作用在引擎的整个生命周期:

  • 在请求进入初期,进行上下文落地(因为广告流量只有一次操作,不像普通支付可以允许用户重试,广告场景下,用户的多次操作需要进行分别计费,并且不太适合利用MQ的ack机制进行重试,因为那需要等流程全部执行完,会影响消息消费速率)
  • 在节点执行结束,进行节点执行状态落地(这样,在遇到需要补偿的情况,可以避免冗余调用,防止不需要重试的系统被其他抖动的系统冲击)
  • 在异步恢复时,获取上下文和节点执行状态集合,以完成事务的最终一致性处理。

2.3存储的调研和选择

业界的选择--数据库

对于支付类业务,其实,最好的是用数据库。业务层的订单表相当于业务请求上下文,会将请求的所需信息落地(没有上下文落地其实也没关系,返回用户失败即可)。

节点执行状态数据存在和订单表同库的另一个表中,即可支持一个在一个本地事务内保证分布式事务的最终一致性逻辑。

业务特性决定了数据库不合适

由于种种原因,我们这里不太适合用数据库,一个是广告上下文太大,且绝大多时候没有用,为了少数异常存到订单表的话太浪费;二是目前采用实时库+历史库的方式进行,没有分库,如果增加了中间状态表,目前的并发量,对数据库压力会很大,但目前搞分库又不是那么必要。

所以数据库不太适合。

公司自研存储的选择和使用

正好,公司自研了一套基于rocksdb的高性能存储,在读写性能和数据结构方面基本可以代替MySQL和Redis。在公司内部被广泛使用。

两个版本,一个是paxos强一致版本,读写性能稍弱,但保证数据强一致;另一个是普通版本,读写性能更高,但不保证强一致,即有可能主从切换会丢数据。

对于带金融属性的业务来说,在理论上的读写性能满足业务要求的情况下,当然是首选强一致的版本了。特别是业务上下文,丢失的结果就是该请求的整个异常恢复流程无法被正常唤起。

然而,理想照进现实,由于该版本之前应对的业务场景较为简单,并发也没有我们这么大,一些底层调优不到位导致服务抖动频繁。

如果是在大厂,就像之前用OB,只要OB有承若数据不丢,那基本不用考虑丢失的问题。如果丢了,我想可能大概率就会把锅抛给存储团队,限时优化之类。

但,我们小厂可都是相亲相爱的一家人,怎么能干这种事。所以选了另一个版本,使用更广泛,更成熟的非强一致版本。而数据丢失的问题由业务自己来想办法。

Part3消息队列的介入

3.1非强一致存储为啥会丢数据

如上图所示,该存储架构采用的是主从模式,数据由主写入,同步到从,当主异常时,进行主从切换,恢复服务。

但是,由于不是强一致协议,写主成功即为成功,当主宕机时,虽然主从切换很快,10秒完成,但还没有来得及同步到从的那部分数据,就会因为因为主从切换而丢失。

怎么办?

3.2消息队列登场

为了应对存储不授信的情况,我们引入了消息队列来实现存储的丢失补偿。

如上图所示,引入延迟消息进入处理流程。

  • 当节点执行发生异常时,发送当前业务上下文到消息队列。如果是正常执行的情况则无需发送。
  • 消息的延迟间隔,要大于主从切换的时间,并且需要小于定时任务的触发间隔。比如,主从切换需要10s,那延迟消息的延迟间隔就设置为30s , 接收消息都重新插入上下文到存储。在节点异常一分钟之后,被定时任务捞取,执行处理。

用两个时间差来覆盖掉主从切换带来的数据丢失的影响。

3.3更进一步--存储降级

那么,更极端的情况,如果整个存储服务持续不可用怎么办?

降级: 自己的命运要把握在自己手中。目的是保证绝大部分服务正常。

  • 监控系统。用于收集和汇报操作存储时的异常,并统计错误率和超时率
  • 一旦错误率和超时率达到阈值(比如持续30s,所有服务全部超时)执行关联脚本。
  • 脚本负责触发配置中心的配置切换,由正常模式切换为柔性模式。
  • 柔性模式下,所有涉及存储读写的操作将被忽略,以保障绝大部分请求可以正常执行。
  • 遇到执行异常的节点,将上下文发送至消息队列,消费时不再插入存储,而是改为直接消费。

Part4总结

本文想从实际的案例出发,给大家提供一种利用消息队列解决问题的思路。希望大家遇到其他问题的时候,可以有所借鉴。毕竟业务场景千千万,只有思路得人心。

高并发系列历史文章微信链接文档

  1. 垂直性能提升 1.1. 架构优化:集群部署,负载均衡 1.2. 万亿流量下负载均衡的实现 1.3. 架构优化:消息中间件的妙用 1.4. 存储优化:mysql的索引原理和优化 1.5. 索引优化补充篇:explain索引优化实战 1.6. 存储优化:详解分库分表

本文分享自微信公众号 - Coder的技术之路(gh_1b3189982966),作者:Coder的技术之路

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 分布式架构设计篇(十)-柔性事务之事务消息详解

    ​ 在 《柔性事务之TCC详解》 和《柔性事务之Saga详解》两文中我们详细剖析了柔性事务的第一个分支补偿型事务。在《刚性事务总结和柔性事务概述》中...

    林淮川
  • 聊聊微服务架构及分布式事务解决方案!

    分布式事务场景如何设计系统架构及解决数据一致性问题,个人理解最终方案把握以下原则就可以了,那就是:大事务=小事务(原子事务)+异步(消息通知),解决分布式事务的...

    Java技术栈
  • 微信朋友圈千亿访问量背后的技术挑战和实践总结

    微信朋友圈包括图片和视频两套业务架构组成,朋友圈图片的特点是请求量大、消耗计算资源较多,视频则主要消耗带宽。

    JackJiang
  • QQ会员2018春节红包抵扣券项目实践与总结

    整体系统是在2017年架构的基础上进行改造扩展,TGW + QZHTTP + RocketMQ + SPP逻辑服务架构 。

    小时光
  • 分布式柔性事务之事务消息详解

    在 《柔性事务之TCC详解》 和《柔性事务之Saga详解》两文中我们详细剖析了柔性事务的第一个分支补偿型事务。在《刚性事务总结和柔性事务概述》中我们介绍过的柔性...

    江帅帅
  • 微服务架构及分布式事务解决方案

    事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:

    烂猪皮
  • 聊聊微服务架构及分布式解决方案

    事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:

    lyb-geek
  • 日订单50万级分布式事务

    作者:伈情,喜玩Java、Python、Golang!热爱架构设计、SOA、微服务、高并发、分布式、性能优化、DevOps、大数据、消息队列等....!在互联网...

    架构师小秘圈
  • 分布式柔性事务之事务消息详解

    在 《柔性事务之TCC详解》 和《柔性事务之Saga详解》两文中我们详细剖析了柔性事务的第一个分支补偿型事务。在《刚性事务总结和柔性事务概述》中我们介绍过的柔性...

    孙玄@奈学教育
  • 如何通过事务消息保障抢购业务的分布式一致性?

    在电商领域,抢购和秒杀是非常普遍业务模式,抢购类业务在快速拉升用户流量并为消息者带来实惠的同时,也给电商系统带来了巨大考验。在高并发、大流量的冲击下,系统的性能...

    猿天地
  • 不了解分布式事务,大公司怎么敢要你!

    消息中间件在分布式系统中的核心作用就是异步通讯、应用解耦和并发缓冲(也叫作流量削峰)。在分布式环境下,需要通过网络进行通讯,就引入了数据传输的不确定性,也就是C...

    Java编程指南
  • 海量服务实践──手Q游戏春节红包项目设计与总结

    1. 需求背景 1.1.红包类别 2017年的手Q春节游戏红包共有刷一刷/AR地图/扫福三种,如下图所示: ? 1.2.体验流程 虽然红包分三种,但在游戏业务...

    小时光
  • IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

    消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一。

    JackJiang
  • 交易系统架构演进之路(四):分布式事务

    上一篇文章我们将整个交易系统进行了微服务化,拆分为了多个相互独立的业务组件,每个业务组件不只是包含自己业务的微服务,还包括了独立管理的数据库。那么,我们来考虑下...

    Keegan小钢
  • 事务与一致性:刚性or柔性?

    在高并发场景下,分布式储存和处理已经是常用手段。但分布式的结构势必会带来“不一致”的麻烦问题,而事务正是解决这一问题而引入的一种概念和方案。我们常把它当做并发操...

    Marky Lumin
  • 分布式架构设计篇(十二)-分布式事务总结篇

    ​ 咱们前面分别对分布式事务的几个分支:XA、2PC、3PC、TCC、Saga、事务消息、最大努力事务进行的详细介绍。本篇作为分布式事务设计的收尾篇...

    林淮川
  • 探秘RocketMQ分布式事务消息的设计原理

    Apache RocketMQ 社区正式发布4.3版本。此次发布不仅包括提升性能,减少内存使用等原有特性增强,还修复了部分社区提出的若干问题,更重要的是该版本开...

    lyb-geek
  • 分布式之事务解决方案

    上一篇:《分布式之Zookeeper核心原理详解》我们对于zookeeper的一致性协议Zab与原子广播,以及根据其原理的一些运用场景有了一个清晰的认知。这一篇...

    斯文的程序
  • 2018-05-17 架构师技能图谱,搞懂这些找工作无敌数据结构常用算法并发操作系统设计模式运维 & 统计 & 技术支持中间件网络数据库搜索引擎性能大数据安全常用开源框架分布式设计设计思想 & 开发模

    Albert陈凯

扫码关注云+社区

领取腾讯云代金券