为何mq(消息缓存队列)
-
应用解耦
使用rpc进行系统通信:用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障或者因为升级等原因暂时不可用,都会造成下单操作异常,影响用户使用体验。
引入rocketmq后:比如物流系统发生故障,需要几分钟才能来修复,在这段时间内,物流系统要处理的数据被缓存到消息队列中,用户的下单操作正常完成。当物流系统回复后,补充处理存在消息队列中的订单消息即可,终端系统感知不到物流系统发生过几分钟故障。 -
流量削峰
例如系统峰值是1000,但中午一小段时间陡增到1万请求,这时候削峰就好了。
-
数据分发
传统rpc方式:
引入rocketmq
优点:解耦、削峰、数据分发
缺点包含以下几点:
-
系统可用性降低
系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。
如何保证MQ的高可用? -
系统复杂度提高
MQ的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。
如何保证消息没有被重复消费?怎么处理消息丢失情况?那么保证消息传递的顺序性? -
一致性问题
A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B系统、C系统处理成功,D系统处理失败。
如何保证消息数据处理的一致性?
分布式事务的一致性保证场景
5件商品,10人下单
- 下单减库存:
前5个人下单了,但就是不付款,后5个人想立马支付的人却没法买(因为库存不够了) - 付款减库存
10人同时下单了,先付款5个人购买正常,后付款的5个人就会报库存不足(超卖) - 预扣库存
先下单的5个人会锁库存(锁2小时),此时页面库存显示为0(后5人现在不能下单),超过2小时用户还没有支付,则取消订单,释放库存
MQ与DB一致性原理(两方事务)
集群搭建
messge queue是topic的一个子集
nameServer相当于注册中心(保存broker(保存消息)的ip和可用状态等)
无论消费者还是生产者都是先访问nameServer,拿到broker的ip缓存到本地,然后再直接访问broker
结合部署结构图,描述集群工作流程【原文链接】:
1,启动Namesrv,Namesrv起来后监听端口,等待Broker、Produer、Consumer连上来,相当于一个路由控制中心。
2,Broker启动,跟所有的Namesrv保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有topic信息。注册成功后,namesrv集群中就有Topic跟Broker的映射关系。
3,收发消息前,先创建topic,创建topic时需要指定该topic要存储在哪些Broker上。也可以在发送消息时自动创建Topic。
4,Producer发送消息,启动时先跟Namesrv集群中的其中一台建立长连接,并从Namesrv中获取当前发送的Topic存在哪些Broker上,然后跟对应的Broker建立长连接,直接向Broker发消息。
5,Consumer跟Producer类似。跟其中一台Namesrv建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。
无状态就是指不需要进行集群中各个节点数据的同步
broker master 是写操作(id为0标识),borker slave(id为1标识)是读操作的,
集群搭建的优缺点
同步复制:producter发消息给broker master,broker master等待所有的slave都同步完数据后再响应producter的请求【消息安全性保证比较高的情况下会用到】
异步复制:producter发消息给broker master,broker master立即响应producter的请求,同时异步的进行所有的slave的数据同步【效率高】
采取多master多slave方式(同步)进行集群搭建
topic其实就是消息类别,并且还需要指定消息在哪个broker上,
mvn clean package -Dmaven.test.skip=true
http://192.168.177.200:8080/#/
安装
yum安装maven教程
yum install -y wget
配置maven源
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
yum -y install apache-maven
启动rocketmq教程
http://rocketmq.apache.org/docs/quick-start/
tail -f 实时动态查询日志
/opt/rocketmq/rocketmq-all-4.8.0-source-release/distribution/target/rocketmq-4.8.0/rocketmq-4.8.0/bin
否则内存所需太大容易启动失败,修改jvm大小
进入:
/opt/rocketmq/rocketmq-all-4.8.0-source-release/distribution/target/rocketmq-4.8.0/rocketmq-4.8.0
nohup sh bin/mqnamesrv -n 192.168.177.200:9876 &
tail -f ~/logs/rocketmqlogs/namesrv.log
在conf/broker.conf 中 加入 brokerIP1=你的公网IP
启动
nohup sh bin/mqbroker -n 192.168.177.200:9876 -c conf/broker.conf autoCreateTopicEnable=true &
tail -f ~/logs/rocketmqlogs/broker.log
【接发消息】
export NAMESRV_ADDR=192.168.177.200:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
export NAMESRV_ADDR=192.168.177.200:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
测试之后可以看到消息如下:
使用jps可查看到以启动
关闭
sh bin/mqshutdown namesrv
sh bin/mqshutdown broker
代码
messge分为如下几部分:
topic(大类别,比如短信消息),tag(小类别,比如短信消息之验证码消息),消息内容(验证码为123)
可靠消息—同步方式发送
高响应消息–异步方式发送
日志消息—单向发送(不需要返回结果)
顺序消息的实现
一个队列只采用一个线程去消费
缺陷记录
参考文章
Rocketmq原理&最佳实践
代码仓库:
https://github.com/apache/rocketmq
阿里云消息队列产品介绍
https://help.aliyun.com/document_detail/29532.html
快速部署教程
http://rocketmq.apache.org/docs/quick-start/
中文官方文档
https://github.com/apache/rocketmq/tree/master/docs/cn
b站视频教程:
https://www.bilibili.com/video/BV1fE411V7Ho?from=search&seid=7550936944502702700
双11,如何抗住千万级tps
如同万能变压器,不论输入电压多高,输出电压都很平稳【流量削峰】