赞
踩
要理解MQ,就不得不了解一下RPC通信模型先
RPC通信模型
比较官方的解释一下: RPC(全程Remote Procedure Call,远程过程调用),是一个可以像调用本地服务一样调用远程服务的计算机通信协议。
模型图:
这里面有必要解释一些术语:
服务提供者(provider):提供具体的调用方法的系统,根据上图也就是服务端,服务端才是方法真正的提供者
服务消费者(consumer):调用服务的系统,根据模型图,也就是客户端
序列化(Serialization):将对象转换为便于进行网络传输的二进制或文本数据的过程
反序列化(Deserialization):二进制或文本数据再还原为对象的过程
RPC调用步骤
1、建立通信:消费者要想调用提供者的方法,首先要和提供者建立通信连接,主要是通过客户端和服务器之间建立TCP连接实现的
2、服务寻址:寻址实现的是确定提供者的IP、端口号以及方法的名称
3、网络传输:消费者发起一个RPC调用时,将调用方法和参数的数据进行序列化传输给提供者,提供者将接收到的参数进行反序列化操作后执行方法
4、服务调用:提供者进行本地调用后得到了返回值,提供者将返回值进行序列化操作后,再通过网络传输将二进制数据发送回给消费者
简单总结一下: 了解了整个流程后,在我的理解里就剩下了一句话对客户端透明的远端服务调用,也就是客户端虽然实际调用的是服务端方法,但RPC通信模型会让客户端觉得调用的是本地方法
好,解释一下为什么了解MQ要先提RPC呢? 因为从本质上看,RPC一般对于客户端来说是一种同步的远程服务调用技术,而一般来说MQ是异步的远程调用
MQ的实质就是一发一存一消费
这也是为什么叫MQ为中间件的缘故
原始模型的两个关键词:消息和队列
消息: 需要传输的数据,可以是最简单的文本字符串,也可以是自定义的复杂格式
队列: 一种先进先出的数据结构,在这里是存放消息的容器,入队即发消息的过程,出队即收消息的过程
过程: 其实看这个图就很清晰了,生产者将消息投递到一个叫做 队列 的容器中,然后再从容器中取出消息,最后转发给消费者
根据消息处理的特点,可以将MQ处理消息的模式分为两类
(2)发布订阅模式(PubSub):一个生产者发送的每一个消息,都会发送到所有订阅了此队列的消费者,也就是广播
在发布订阅模型中,存放消息的容器变成了主题(主题也是一个队列),订阅者在接收消息之前需要先订阅主题,最终,每个订阅者都可以收到同一个主题的全量消息
可以看到和队列模式唯一不同的就是,发布订阅模式中的一份消息数据可以被多次消费
消息队列中间件是分布式系统中的重要组件
目前使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、RocketMQ
略微介绍一下各位,有个印象:
特性
缺点
特征
优点
缺点
特征
优点
缺点
特征
优点
缺点
特征
先画个表格对比一下
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
单机吞吐量 | 万级 | 万级 | 十万级(单机万级) | 十万级 |
topic数量对吞吐量的影响 | \ | \ | topic可以达到千的级别,吞吐量会有较小幅度的下降 这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic | topic从几十个到几百个的时候,吞吐量会大幅度下降 同等机器下,topic数量不要过多,如果topic一定要大,那么需要增加更多的机器资源 |
消息写入性能 | RAM约为RocketMQ的1/2 Disk的性能约为RAM性能的1/3 | \ | 很好 每条10字节测试:单机单broker约7w/s | 非常好 每条10字节测试:百万条/s |
可用性 | 高(主从架构) master提供服务,slave仅做备份。采用镜像模式,数据量大时可能产生性能瓶颈 | 高(主从架构) 基于ZooKeeper+LevelDB的主从实现方式 | 高(分布式架构) 支持多master、多master多slave模式,异步复制模式,同步双写 | 非常高(分布式架构) 支持replica机制,leader宕机后,备份自动顶替,并重新选举leader(基于Zookeeper) |
消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒级以内 |
消息可靠性 | 可以保证数据不丢失,有slave节点做备份 | 有较低的概率丢失数据 | 经过参数优化配置,理论上可以做到0丢失 | 经过参数优化,理论上可以做到0丢失 |
持久化能力 | 内存、文件 支持数据堆积,但数据堆积反过来影响生产速率 | 内存、文件、数据库 | 磁盘文件 | 磁盘文件 只要磁盘容量够,就可以做到无限消息堆积 |
是否有序 | 若想有序,只能使用1个Client | 可以支持有序 | 有序 | 多Client保证有序 |
消息批量操作 | 不支持 | 支持 | 支持 | 支持 |
集群 | 支持 | 支持 | 支持 | 支持 |
事务 | 不支持 | 支持 | 支持 | 不支持,但可以通过Low Level API保证仅消费一次 |
到了最终要做抉择的时候了
总结一下
没有万金油,看自己需求进行选择
ZeroMQ小而美,RabbitMQ大而稳,Kafka和RocketMQ快而强劲
求保险,技术挑战不高的,RabbitMQ是首选
求性能,有事务性要求高的,技术实力强的,可以试试RocketMQ
大数据领域、日志采集,Kafka是业界标准,无脑选
消息队列在实际应用中的常用使用场景有:异步处理、应用解耦、流量削峰和消息通讯
那我们就从一个实际场景来白话的解释一下这些看起来很高大上的场景
举个栗子
购物系统中的订单支付:在订单支付成功后,需要更新订单状态、更新用户积分、通知商家有新订单、更新用户标签几个操作。
那么在没有MQ之前,我们老老实实的一步接一步做,像这样
但这样的问题是什么,慢,太慢了,非得是上一步完成了才能开始下一步
所以引入MQ后,整个流程是这样的
看见没有,订单支付只需要关注它的主要流程更新订单状态即可,然后就把消息丢到MQ,其他的不核心的东西就由MQ来通知
这就是MQ解决的最核心的问题应用解耦,也就是只关注最核心的部分
改造前订单系统依赖3个外部系统,改造后仅依赖MQ,那么后续业务的扩展,也不需要对订单系统进行修改,从而保证了核心流程的稳定性,降低了维护成本
异步通信:MQ的引入,更新用户积分、通知商家、更新用户标签这些步骤不再是串行的了,而是变成了异步执行,这减少了订单支付的整体耗时,提升了订单系统的吞吐量
流量削峰:队列转储了消息,做了一个中间站,对于超出系统承载能力的场景,"MQ"作为漏斗进行限流保护,就是说把最高的峰值削一部分给峰谷,就好像把波浪线修成直线一样,均衡一下
消息的延时消费:队列本身的特征是先进先出,也就是说是有序的,利用队列+定时任务就能实现消息的延时消费
就用网上用烂了的几张图与传统方法进行对比,显示一下MQ的优越
场景:用户注册后,需要发送注册用剑和注册短信
传统做法:串行、并行
场景:用户下单后,订单系统通知库存系统
传统做法:订单系统调用库存系统的接口,一旦一个系统无法使用,必定会导致另一个系统也无法使用
引入MQ后:订单系统和库存系统不再直接交互
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户下单成功
库存系统:订阅下单的队列,采用推/拉的方式,获取下单信息,根据下单信息,进行库存操作
假如其中一个系统无法正常使用,只要MQ健在,另一个系统将不受影响
场景: 秒杀或者团抢活动,一般因为流量过大,导致流量暴增,应用挂掉
传统方法: 加服务器
引入MQ后:在应用前端加入消息队列,秒杀时将消息不断丢入队列,等待业务根据规则读取队列中的消息进行处理
场景:大量日志进行传输
引入MQ后: kafka的优秀展示场景
场景:分为点对点通讯(也就是单向私聊)和聊天室(也就是群聊或双向私聊)
点对点通讯: 两个客户端之间公用一个队列
聊天室通讯:多个客户端订阅同一主题(注意这里是订阅不是消费,说明一个消息可以被多次消费)
到此,结束,撒花,放烟花!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。