RabbitMQ

队列对比
队列 ActiveMq RabbitMq RocketMQ Kafka
性能 6000+ 12000+ 10万+ 百万
多语言支持 支持 支持 支持 支持
社区活跃度
综合评价 成熟,性能较弱缺乏大规模吞吐场景的应用 性能较好,社区活跃管理界面丰富 内部机制很难了解,难定制 模型简单。接口易用,文档少,支持语言少 天生分布式,性能最好,运维难度大
使用docker进行安装
  • 下载management的版本,带web界面
  • 命令:
docker run -d --name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost  -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:3.7.13-management
  • 参数:

    • -d:后台运行
    • --name : 指定容器名
    • -p : 端口映射
    • --hostname : rabbitmq主机名
    • -e RABBITMQ_DEFAULT_VHOST=my_vhost 虚拟机名
    • -e RABBITMQ_DEFAULT_USER=admin 用户名
    • -e RABBITMQ_DEFAULT_PASS=123456 密码
  • 相关概念:

    • 发送消息 生产者
    • 队列、接收消息 消费者
    • 交换机:做了一层抽象。发送消息,和队列通过交换机来做转发。交换机会根据分发策略把消息转给队列。
    • 虚拟主机:支持权限控制,最小粒度为虚拟主机,一个虚拟主机可以包含多个交换机,队列,绑定
    • 队列:缓存消息的容器
    • 绑定: 设置交换机与队列的关系
  • 交换机

    • 扇形交换机:Fanout exchange
    • 直连交换机:Direct exchange
    • 主题交换机:Topic exchange
    • 首部交换机:Headers exchange
  • 应用场景(优点)

    • 解耦
    • 异步
    • 削峰
  • 缺点:

    • 增加了系统的复杂性
    • 增加了维护的难度
    • 降低系统的稳定性:引入依赖越多,越容易挂掉
问题
  • 消息的重复消费:
    • 发送端

      • 发送端发送消息给中间件,中间件收到消息并成功存储,此时的中间件出现了问题,导致发送端没有收到发送成功的返回进行重试从而产生重复
      • 中间件由于负载过高,响应变慢,成功把消息储存到中间件后,返回成功时间超时进行重试从而产生重复
      • 消息中间件成功写入消息存储,在返回结果时,出现网络问题,导致超时,而重试时,网络恢复出现重复
    • 消费端

      • 消费者收到消息进行处理,处理完毕程序出现问题,中间件不知道处理结果,会再次投递
      • 消费者收到消息进行处理,处理完毕后网络出现问题,中间件没有收到处理结果,再次投递
      • 消费端处理消息花费时间过长,中间件由于消息超时会再次投递。
      • 收到消费者的处理结果,中间件出现问题,未及时更改状态,再次投递
      • 处理完毕后,消息中间件收到结果,但是遇到消息存储故障,没能更新状态,在次投递

发送端产生消息重复的主要原因是:消息成功写入消息存储后,因为各种原因使得消息发送端没有收到成功的返回结果,并且进行重试,因而导致的重复。
消息接收端消息重复的主要原因是:消息接收者成功处理完消息后,消息中间件不能及时更新投递状态造成。

  • 如何解决重复消费:
    • 幂等性控制:多次调用得到相同的结果
    • 消费者发送消息进行数据更新时,需要带上数据的版本号。
    • 去重表:利用数据库的特性实现幂等。常用的思路就是在表上构建一个唯一性的索引,保证某类数据一旦执行完毕,后续同样的请求不在处理了。或者创建一个去重表,每次操作时都去该表中查看一下id是否已经存在了,如果存在则直接返回。
如何保证数据的可靠性传输
  • 生产者弄丢了数据

    • 选择用rabbitmq提供的事务功能。生产者在发送数据的之前开启RabbitMQ事务 ,channel.txSelect . 然后发送消息。如果消息没有被成功的接收到,那么生产者会收到异常报错。此时可以回滚事务,然后重试发送。如果收到了消息可以提交事务。缺点 就是吞吐量会下降,太耗性能。
    • 开启confirm模式。开启之后,每次都会分配一个唯一的id,如果写入了队列中,rabbitmq会回传一个ack,如果没有处理这个消息,会回调你的nack接口。告诉你接收失败,可以重试。
    • 事务机制和confirm最大的区别是 事务时同步的。你提交一个事务后悔阻塞在哪里。confirm是异步的。你发送消息之后会发送下一个消息,然后那个消息rabbitmq接收后会异步回调你的接口
  • rabbitmq 自己弄丢了数据

    • ,必须开启rabbitmq的持久化,就是消息会写入之后持久化到硬盘上,哪怕是rabbitmq挂了重启之后,数据还是能恢复的。
      • 设置持久化的两个步骤:
        • 创建queue和交换器的时候将其设置为持久化。这样可以保证rabbitmq持久化相关的元数据。但是不会持久化队列中的数据
        • 发送消息的时候将消息的deliveryMode设置为2,就是将消息设置为持久化(默认为2,可不设置)。
  • 消费端弄丢了数据:

    • rabbitmq如果丢失了数据,主要是因为你消费的时候,刚消费到,还没有处理,结果进程挂了,比如重启
      • 用rabbitmq提供的ack机制。关闭自动ack,进行手动ack.

实际项目中遇到的问题:

  • 之前遇到过这样的一个问题, 由于发送方与消费方的速度不匹配,在压测时,导致大量数据在队列中积压,大约有10万条,因为是测试数据,当时采用的方式比较暴力,直接删除队列,在新建队列,完成消息的删除。但是在生产上是不能这么干滴!!!

  • 大量数据持续挤压怎么解决?

    • 先修复consumer的问题
    • 新建几个队列,具体数量自己把控。
    • 新建一个程序,不做耗时处理,将现在积压的数据分发到新建的队列中。
    • 每个队列绑定一个consumer,进行业务处理。
    • 处理完毕后,恢复之前的程序部署

消费方的业务处理时间可能比较长,最好采用多线程和多consumer进行消费。

程序实现

发送方
  • 配置文件:
    关于rabbitmq的主机,端口等我直接写死在程序中,可通过properties文件注入,方便配置,基于rabbitTemplate进行代码封装


    配置.png
  • 初始化


    初始化.png

此处说下callback和returncallbakc的执行时机:
消息没有到达exchange,则confirm回调,ack=false
消息到达exchange,则confirm回调,ack=false
exchange到queue成功,则不回调returnCallBack。
exchange到queue失败,则回调returnCallBack,在回调confirmCallBack.需设置mandatory=true,否则不回回调,消息就丢了

  • 消息发送


    消息发送.png

上面为封装后对外开放的接口,可为此方法编写重载方法。对外只暴露 泛型参数T

  • 消费方:两种实现方式
    • 使用注解:@RabbitListener(queues = "notify.payment")


      手动ack.png
    • 实现ChannelAwareMessageListener,并在container中注入


      image.png

      image.png

消费方推荐使用多线程进行处理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • RabbitMQ 简介 MQ 消息队列,上承生产者,下接消费者。从生产者侧获取消息,然后将消息转发给消费者。由此可...
    2205阅读 3,425评论 1 11
  • 应用场景 异步处理 场景说明:用户注册后,需要发注册邮件和注册短信,传统的做法有两种: 1.串行的方式 2.并行的...
    lijun_m阅读 1,773评论 0 3
  • 网上rabbitmq的学习日志非常丰富,官网文档也很完美,这里主要记录学习和部署过程中的一些记录。会按以下菜单进行...
    恐龙打酱油阅读 2,503评论 0 4
  • 不知道你们有没有被比你年长的所谓的“过来人”这样教导过:在大学,重要的是学会与别人社交,多交朋友,多认识人,其他的...
    昔我往矣__阅读 1,407评论 4 7
  • 继续延续向上的力度还有,看中枢的第三类买点能不能在明后二天走出?否则就会是中枢震荡。3254点开始的5分钟级别向上...
    禅中悟缠阅读 112评论 0 1