一、系统间通信技术
一般来说,分布式应用的子系统之间并不是完全独立的。他需要相互通信来共同完成某个功能。业界通常有两种方式来实现系统间的通信,其中一种是基于远程调用的方式(即RPC),另一种是基于消息队列的调用方式。如下图:
RPC调用方式:
消息队列调用方式:
二、为何要用消息队列?
比较以上两种模型,显然:RPC模型类似:“一问一答”。消息队列模型类似:“留言”。下面我们结合具体场景理解使用消息队列的几个重要作用。
(1)异步
模拟场景:
如下图,一个系统要拓展一个用户注册功能,注册成功后可以收到邮件通知。
思考:
采用(如图1)显然用时较长。采用(如图2)虽然减少了耗时。但如何保证邮件能够发送成功?于是乎我们想到将邮件统一发送到一个地方(如图3),再从类似于信箱里取出邮件。这样注册和发送邮件不再是同步操作,用时较少,可用性较高。
(2)解耦
模拟场景:
A系统向BCD系统发送数据,先来看两幅图:
思考:
显然,未使用消息队列前,A系统直接和BCD交互。同时兼顾着各种问题才能保证数据发送成功。使用消息队列后,A系统再也不用考虑BCD烦人的事情。也不关心取数据的是BCD还是EFG。A的主钻任务就是向MQ中发数据。实现和A和其他系统的解耦。事实上,消息队列在这里起到了很好的“中间”作用。这也是它为什么被称为”消息中间件”的原因。
(3)流量削峰
模拟场景:
双十一秒杀活动(高并发场景),假设A系统处理请求能力3000次/s,MsSQL执行sql语句3000条/s。
思考:
显然,在高并发场景下使用消息队列。可以有效起“暂存”的作用,削弱高峰期流量,有效缓解数据库压力,维护系统稳定性。
(4)事务最终一致性
模拟场景:
支付宝转存余额宝:
支付宝A表 : 余额3000元
余额宝B表 : 余额1000元
账户:userid =123
现在我们从A表(支付宝)中转账1000元到B表(余额宝),则至少要执行两个操作(伪代码):
1)从支付宝账户表A扣除1000元:update A set money = money-1000 where userid= 123;
2)余额宝账户B增加1000元:update B set money = money+1000 where userid= 123;
思考:
这里问题的在于如何能够让这两步操作在一个事务中,如果这两个账户表在同一个数据库中。那我们可以用事务的方式解决:
begin transaction
update A set money = money-1000 where userid= 123;
update B set money = money+1000 where userid= 123;
end transaction
commit;
但是当系统业务繁杂时,通常我们会将A、B 2个表放在两套不同的数据库中。此时,原先通过数据库提供的事务处理方式则无法解决该问题。这就是我们常说的分布式事务的问题。
业界的很多实践方案中,通常可以借助消息队列来处理此问题。简单来讲,就是在支付宝账户扣钱的同时,发送一条让余额宝账户加钱的消息到消息队列,余额宝系统一旦接收到该消息,就操作数据库在自己的账户中加钱。
那如何保证数据库操作和消息队列操作在同一个事务中呢?这里可以通过添加事件来解决。另外,任何事物都有两面性。本小节主要介绍了使用消息队列的优势。当然,他还有许多缺点,这些我们后期再做详细介绍。
小结:
1)消息队列主要应用于分布式系统;
2)使用消息队列的作用:异步、解耦、流量削峰、事务最终一致性
本人职场小白,文章中难免出现理解不到位或错误的地方,还望大佬们批评指正。也欢迎你评论,留言,点赞!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。