技术标签: 应用解耦 削峰填谷 消息中间件 流量控制 百图解码支付系统设计与实现 分布式
这是《百图解码支付系统设计与实现》专栏系列文章中的第(18)篇,也是流量控制系列的第(4)篇。点击上方关注,深入了解支付系统的方方面面。
本篇重点讲清楚分布式消息中间件的特点,常见消息中间件的简单对比,在支付系统的应用场景,比如削峰填谷,系统应用间的解耦,事务消息等。
内容偏入门介绍,已经使用过消息中间件的同学可以不用往下看了。
在流量控制系列文章中的前四篇,分别介绍了固定时间窗口算法、滑动时间窗口算法、漏桶原理、令牌桶原理,应用场景和java版本的核心代码。
我们做个简单回顾:
固定窗口:算法简单,对突然流量响应不够灵活。超过流量的会直接拒绝,通常用于限流。
滑动窗口: 算法简单,对突然流量响应比固定窗口灵活。超过流量的会直接拒绝,通常用于限流。
漏桶算法:在固定窗口的基础之上,使用队列缓冲流量。提供了稳定的流量输出,适用于对流量平滑性有严格要求的场景。
令牌桶算法:在滑动窗口的基础之上,使用队列缓冲流量。提供了稳定的流量输出,且能应对突发流量。
今天讲的分布式消息中间件在支付场景的削峰填谷用得比较多,且对精度没有那么苛刻的场景,比如集群低到1TPS,就无法做到。
削峰:在流量高峰期,通过消息中间件暂存大量的请求,减少对后端系统的直接压力。
填谷:在低峰期,逐渐处理这些积累的请求。
这种方法能有效平衡系统负载,防止在高峰时段系统崩溃。
我们一般使用消息中间件实现削峰填谷。下面是一个支付引擎自产生消的示例图。收到支付请求后,先扔到消息中间件,然后启用新的监听线程去消费。通过控制消费线程数来控制流量。
比如一下来了1000个请求,一共10台机器,每台机器消费线程只开5个,每个请求处理500ms,那么每秒就处理100个请求,共耗时10秒处理完。
消息中间件还有一个作用,就是应用间的解耦。比如支付成功后,渠道网关通过消息中间件返回给支付引擎。
消息中间件有很多,这里简单对比 RocketMQ、RabbitMQ 和 Kafka在性能、可靠性、易用性、功能特性、适用场景等方面的不同。如下:
性能
可靠性
易用性和管理
功能特性
适用场景
结论
另外,我也只是简单介绍,大家实际应用的时候,根据实际情况去选型,建议是做多方了解后,部署验证后才规模使用。不过话说回来,这几款分布式消息中间件的技术非常成熟了,除了几个顶流的互联网公司外,基本可以随便用,哪个手熟就使用哪个。
脑裂问题
曾经在生产环境碰到过RabbitMQ脑裂问题,交易全部中断。在分布式环境中完全避免也不现实,建议加强监控。
消费线程数问题
消费线程要合理设置,太多,可能达不到削峰填谷的效果,太少,消息有可能会积累,影响处理时效。
比如支付是有时效,积压太久就会导致用户放弃支付。
消息积压应对
提前做好预估,以及监控。一旦把中间件压爆,可能整个交易系统。
持久化与恢复
防止系统崩溃导致的数据丢失。
事务消息
在需要保证数据一致性的场景中,合理使用事务消息。
消息确认与重试
合理设置消息确认机制和重试策略。如果本次无法处理,一定再抛回去。建议不要先确认再处理,万一确认后,本机又无法处理,消息就丢失了。
消息中间件在支付系统中核心有几个核心应用场景:
基本上,消息中间件在支付系统中无所不在。
先声明,以下代码纯演示,生产环境需要考虑更多因素。
比如支付场景下,接收请求后,先放到队列,然后使用单独的消费线程去消费。以下是简单示例。
1. 添加依赖
首先,你需要在项目的 pom.xml 文件中添加 RocketMQ 的依赖:
<dependencies>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>5.1.4</version>
</dependency>
</dependencies>
确保使用最新版本的依赖。
2. 创建生产者 (Producer)
创建一个生产者以发送消息到 RocketMQ 服务器:
public class PayServiceImpl implements PayService {
@Autowired
private MQProducer mqProducer;
public PayOrder pay(PayRequest request) {
PayOrder payOrder = buildPayOrder(request);
// 前置处理,比如校验、保存DB等
... ...
// 发送到队列
Message msg = buildMessage(payOrder);
mqProducer.send(msg);
// 前置处理
... ...
return payOrder;
}
public boolean processPay(PayOrder payOrder) {
// 外发处理
... ...
}
}
3. 创建消费者 (Consumer)
创建一个消费者来接收从 RocketMQ 发送的消息:
public class PayConsumerServiceImpl implements PayConsumerService {
@Autowired
private MQConsumer mqConsumer;
@Autowired
private PayService payService;
@Postconstruct
public void init() {
mqConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
payService.processPay(buildPayOrder(msg);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
}
}
再次声明,上述代码纯演示,在生产环境中,需要考虑更复杂的场景和错误处理机制。
通过使用分布式消息中间件进行并发流量控制,支付系统可以更有效地应对高并发场景。能很好地提高系统整体的稳定性和可靠性,毕竟瞬间的大流量被缓冲到了消息中间件里。
但有些场景无法使用消息中间件,比如要求整个集群低到1TPS,又或者对接了外部上百个渠道,每个渠道要求不一样,有些要求最高20TPS,有些最高100TPS,使用消息中间件不好实现,就需要前面文章介绍的手撸一个漏桶或令牌桶。
下一篇聊聊阿里开源的流量控制与熔断利器:Sentinel。
专栏地址:百图解码支付系统设计与实现
《百图解码支付系统设计与实现》专栏介绍
《百图解码支付系统设计与实现》专栏大纲及文章链接汇总(进度更新于2023.1.15)
领域相关(部分):
支付行业黑话:支付系统必知术语一网打尽
跟着图走,学支付:在线支付系统设计的图解教程
图解收单平台:打造商户收款的高效之道
图解结算平台:准确高效给商户结款
图解收银台:支付系统承上启下的关键应用
图解支付引擎:资产流动的枢纽
图解渠道网关:不只是对接渠道的接口(一)
技术专题(部分):
交易流水号的艺术:掌握支付系统的业务ID生成指南
揭密支付安全:为什么你的交易无法被篡改
金融密语:揭秘支付系统的加解密艺术
支付系统日志设计完全指南:构建高效监控和问题排查体系的关键基石
避免重复扣款:分布式支付系统的幂等性原理与实践
支付系统的心脏:简洁而精妙的状态机设计与核心代码实现
精确掌控并发:固定时间窗口算法在分布式环境下并发流量控制的设计与实现
精确掌控并发:滑动时间窗口算法在分布式环境下并发流量控制的设计与实现
文章浏览阅读2.9k次,点赞8次,收藏14次。测试主要做什么?这完全都体现在测试流程中,同时测试流程是面试问题中出现频率最高的,这不仅是因为测试流程很重要,而是在面试过程中这短短的半小时到一个小时的时间,通过测试流程就可以判断出应聘者是否合适,故在测试流程中包含了测试工作的核心内容,例如需求分析,测试用例的设计,测试执行,缺陷等重要的过程。..._测试过程管理中包含哪些过程
文章浏览阅读870次,点赞16次,收藏19次。1.背景介绍政府数字化政务是指政府利用数字技术、互联网、大数据、人工智能等新技术手段,对政府政务进行数字化改革,提高政府工作效率,提升政府服务质量的过程。随着人工智能(AI)和机器学习(ML)技术的快速发展,政府数字化政务中的人工智能与机器学习应用也逐渐成为政府改革的重要内容。政府数字化政务的人工智能与机器学习应用涉及多个领域,包括政策决策、政府服务、公共安全、社会治理等。在这些领域,人工...
文章浏览阅读219次,点赞2次,收藏4次。系统主要的用户为用户、管理员,他们的具体权限如下:用户:用户登录后可以对管理员上传的学习视频进行学习。用户可以选择题型进行练习。用户选择小程序提供的考研科目进行相关训练。用户可以进行水平测试,并且查看相关成绩用户可以进行错题集的整理管理员:管理员登录后可管理个人基本信息管理员登录后可管理个人基本信息管理员可以上传、发布考研的相关例题及其分析,并对题型进行管理管理员可以进行查看、搜索考研题目及错题情况。_mysql刷题软件
文章浏览阅读1.4k次。myelipse里有UML1和UML2两种方式,UML2功能更强大,但是两者生成过程差别不大1.建立Test工程,如下图,uml包存放uml类图package com.zz.domain;public class User {private int id;private String name;public int getId() {return id;}public void setId(int..._根据以下java代码画出类图
文章浏览阅读174次。需求:一个topic包含很多个表信息,需要自动根据json字符串中的字段来写入到hive不同的表对应的路径中。发送到Kafka中的数据原本最外层原本没有pkDay和project,只有data和name。因为担心data里面会空值,所以根同事商量,让他们在最外层添加了project和pkDay字段。pkDay字段用于表的自动分区,proejct和name合起来用于自动拼接hive表的名称为 ..._flume拦截器自定义开发 kafka
文章浏览阅读380次。原标题:Java Spring中同时访问多种不同数据库 多样的工作要求,可以使用不同的工作方法,只要能获得结果,就不会徒劳。开发企业应用时我们常常遇到要同时访问多种不同数据库的问题,有时是必须把数据归档到某种数据仓库中,有时是要把数据变更推送到第三方数据库中。使用Spring框架时,使用单一数据库是非常容易的,但如果要同时访问多个数据库的话事件就变得复杂多了。本文以在Spring框架下开发一个Sp..._根据输入的不同连接不同的数据库
文章浏览阅读3.6k次,点赞9次,收藏25次。本案例描述了晶振屏蔽以及开关电源变压器屏蔽对系统稳定工作的影响, 硬件设计时应考虑。_eft电路图
文章浏览阅读1.1k次。对于物料价格的更改,可以采取不同的手段:首先,我们来介绍MR21的方式。 需要说明的是,如果要对某一产品进行价格修改,必须满足的前提条件是: ■ 1、必须对价格生效的物料期间与对应会计期间进行开启; ■ 2、该产品在该物料期间未发生物料移动。执行MR21,例如更改物料1180051689的价格为20000元,系统提示“对于物料1180051689 存在一个当前或未来标准价格”,这是因为已经对该..._mr21 对于物料 zba89121 存在一个当前或未来标准价格
文章浏览阅读7.4k次,点赞3次,收藏13次。[文章导读]联想启天M420是一款商用台式电脑,预装的是win10系统,用户还是喜欢win7系统,该台式机采用的intel 8代i5 8500CPU,在安装安装win7时有很多问题,在安装win7时要在BIOS中“关闭安全启动”和“开启兼容模式”,并且安装过程中usb不能使用,要采用联想win7新机型安装,且默认采用的uefi+gpt模式,要改成legacy+mbr引导,那么联想启天M420台式电..._启天m420刷bios
文章浏览阅读2.7k次,点赞2次,收藏9次。一,为什么要冗余数据互联网数据量很大的业务场景,往往数据库需要进行水平切分来降低单库数据量。水平切分会有一个patition key,通过patition key的查询能..._保证冗余性
文章浏览阅读88次。是时候闭环Java应用了 原创 2016-08-16 张开涛 你曾经因为部署/上线而痛苦吗?你曾经因为要去运维那改配置而烦恼吗?在我接触过的一些部署/上线方式中,曾碰到过以下一些问题:1、程序代码和依赖都是人工上传到服务器,不是通过工具进行部署和发布;2、目录结构没有规范,jar启动时通过-classpath任意指定;3、fat jar,把程序代码、配置文件和依赖jar都打包到一个jar中,改配置..._那么需要把上面的defaultjavatyperesolver类打包到插件中
文章浏览阅读909次。1.得下载一个番茄插件,按alt+g才可以有函数跳转功能。2.不安装番茄插件,按F12也可以有跳转功能。3.进公司的VS工程是D:\sync\build\win路径,.sln才是打开工程的方式,一个是VS2005打开的,一个是VS2013打开的。4.公司库里的线程接口,在CmThreadManager.h 里,这个里面是我们的线程库,可以直接拿来用。CreateUserTaskThre..._番茄助手颜色