全球先进公司建成全球首座8英寸氮化镓代工厂
06-06
作者在高并发场景下亲自开发了一个简单、稳定、可扩展的延迟消息队列框架,具有精确的定时任务和延迟队列处理功能。开源半年多以来,已成功为十几家中小企业提供精准定时调度解决方案,并经受住了生产环境的考验。
为了让更多童鞋受益,现给出开源框架地址:欢迎Star源码,也可以pr你的牛逼代码。之前写过:消息队列中间件在很多高并发系统中都会用到。
那么,问题来了,为什么在高并发系统中要使用消息队列中间件呢?如果你立志成为一名高级架构师,你有没有想过这个问题?本文汇集了众多技术专家的编程思想,由冰河收集整理。在此,向那些为技术发展默默贡献的前辈表示感谢!本文已收录于: 现在假设一个场景,用户需要发送短信才能成功下单。
如果没有消息队列,我们??会选择同步调用短信接口,等待短信发送成功。现在假设短信接口实现有问题或者短时间内已经达到短信发送限制。
这时候你是应该选择重试几次还是放弃发送呢?这里的设计会很复杂。如果使用消息队列,我们??选择将短信操作封装成消息发送到消息队列。
消息队列通知服务发送文本消息。即使出现上述问题,你也可以选择将消息放回消息队列中等待。
处理。消息队列的好处通过上面的例子,我们看到消息队列完成了一个异步解耦的过程。
发送短信时,我们只需要保证短信成功发送到消息队列中,然后就可以做其他事情了;其次,设计变得更加简单。在点餐场景中,我们不需要过多考虑发送短信的问题。
我们就把它留给消息队列管理。发送短信可能会有延迟,但保证最终一致性。
消息队列特性与业务无关,只是消息分发。先进先出,先发货,先到达。
容灾:动态增删节点和消息持久化。性能:吞吐量提高,系统内部通信效率提高。
消息队列的两种模式。点对点模式。
点对点模型用于消息生产者和消息消费者之间的点对点通信。在Pub/Sub发布-订阅模型中,多个发布者向一个Topic发送消息,系统将这些消息传递给多个订阅者。
高并发系统为什么要用消息队列? (1)业务解耦成功完成了一次异步解耦过程。发送短信时,只需确保将其放入消息队列即可,然后执行其余操作。
交易只关心本质流程。当它需要依赖其他东西但又不是那么重要时,可以通知它,而无需等待结果。
每个成员不需要受到其他成员的影响,可以更加独立,只需通过简单的容器进行连接。对于我们的订单系统来说,订单最终支付成功后,我们可能需要给用户发送短信积分什么的,但实际上这已经不再是我们系统的核心流程了。
如果外部系统很慢(比如短信网关速度不好),那么主流程就会花费更长的时间,用户肯定不希望等几分钟才看到结果就点击支付。那么我们只需要通知短信系统“我们支付成功”即可,而不必等待其处理。
(2)最终一致性主要通过记录和补偿来处理;在做一切不确定的事情之前,先记录事情,然后再做不确定的事情。其结果通常分为三种类型:成功、失败或不确定;如果成功的话,我们就可以清理记录的东西了。
对于失败和不确定性,我们可以使用计划任务重做所有失败的事情,直到成功。通过将任务存储在队列中以确保其最终被执行来保证最终一致性。
最终一致性意味着两个系统的状态保持一致,要么都成功,要么都失败。当然,是有时间限制的。
理论上是越快越好,但实际上,在各种异常情况下,达到最终一致状态可能会有一定的延迟,但两个系统的最终状态是相同的。业界有一些消息队列是为了“最终一致性”而设计的,比如Notify(阿里巴巴)、QMQ(去哪儿)等,它们的设计初衷是为了在交易系统中提供高可靠的通知。
让我们使用银行的转账流程来了解最终一致性。转移要求非常简单。
如果A系统成功扣款,B系统也一定会加款成功。否则就会像什么都没发生一样回滚。
但这个过程中可能出现很多意外:A成功扣款,但无法调用B充值接口。 A成功扣款,虽然调用B的加钱接口成功,但是网络异常导致获取最终结果超时。
A扣钱成功,B加钱失败。 A想要退回被扣的钱,但A的机器坏了。
可见,真正完成这件看似简单的事情,并不是那么容易。从技术角度来看,所有跨JVM一致性问题的通用解决方案是:强一致性和分布式事务,但实现难度太大,成本太高。
最终一致性主要采用“记录”和“补偿”的方式。在做一切不确定的事情之前,先把事情记录下来,然后再做不确定的事情。
结果可能是:成功、失败或不确定。 “不确定性”(如超时等)可以等同于失败。
。如果成功了,就可以清理记录的东西了。
对于失败和不确定性,可以依靠计划任务等方法重做所有失败的事情,直到成功。回到刚才的例子,当A成功扣钱时,系统在库中记录了给B的“通知”(为了保证最高的可靠性,系统可以通知系统B加钱并成功扣钱)。
在本地事务中维护)。如果通知成功,该记录将被删除。
如果通知失败或不确定,我们将通过计划任务进行补偿,直到我们将状态更新为正确的状态。消息可能会重复。
注意消息的重复性和幂等性。 (3)广播如果没有消息队列,每次访问新的业务,我们都需要连接一个新的接口;有了消息队列,我们??只需要判断消息是否发送到消息队列,新访问的接口订阅了相关消息,自己处理即可。
(4)错峰和流量控制使用消息队列转储两个系统的通信内容,并在下游系统有能力处理这些消息时处理这些消息。试想一下,上游和下游处理事情的能力是不同的。
例如,Web前端每秒承受数千万次请求并不是什么神奇的事情。你只需要添加更多的机器并构建一些LVS负载均衡设备和Nginx即可。
然而,数据库的处理能力非常有限。即使使用SSD对数据库和表格进行加点,单机的处理能力仍然是万级别。
出于成本考虑,我们不能期望数据库机器的数量能够赶上前端。系统之间也存在这个问题。
比如短信系统可能会因为缺点(每秒几百个请求)而卡在网关,这和前端并发不是一个数量级。不过,如果用户在晚上半分钟左右收到短信,一般不会有太大问题。
如果没有消息队列,并不意味着两个系统之间无法实现协商、滑动窗口等复杂的解决方案。然而,系统的复杂度呈指数级增长,存储必须在上游或下游进行,并且必须处理时序、拥塞等一系列问题。
而每当处理能力出现差距时,就需要开发一套单独的逻辑来维护这套逻辑。因此,使用中间系统转储两个系统的通信内容,然后在下游系统有能力处理这些消息时再处理这些消息是一种比较常见的方法。
实现分布式事务 在上一篇文章《12张图带你彻底理解分布式事务产生的场景和解决方案!!》中,有朋友留言索要案例demo。这里,我将我基于最终消息一致性的开源分布式事务框架的地址mykit-transaction-message发送出去。
框架中有非常完整的demo示例。 mykit-transaction-message是基于猫大师编写的神话框架。
只有站在巨人的肩膀上,才能看得更远! !朋友们,请践行武德,不要无偿卖淫,记得在github和gitee上给star。如果您有什么想说的,可以在文末留言! ! github:总而言之,消息队列并不是万能的。
对于需要强事务保证且对延迟敏感的应用程序,RPC 优于消息队列。对于一些无关紧要的事情,或者对别人来说很重要但自己不太关心的事情,可以使用消息队列来做。
支持最终一致性的消息队列可以用来处理对延迟不太敏感的“分布式事务”场景,并且可能是比繁琐的分布式事务更好的处理方式。当上下游系统的处理能力存在差距时,利用消息队列创建通用的“漏斗”。
当下游有能力处理时进行分发。如果下游有很多系统关心你的系统发送的通知,就果断使用消息队列。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-06
06-18
06-18
06-17
06-18
06-18
06-18
06-17
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用