消息队列

作用

1.异步处理(无需同步阻塞,给予用户体验)
2.应用解耦(远程调用一方改变接口,另一微服务必须同时改写源代码)
3.流量削峰(防止百万流量冲击服务器,防止宕机)

两种模式

1.点对点(队列,多个人监听,只有一个人能接收消息)
2.发布订阅模式(多个人可以同时接收消息)

协议

消息队列遵循的协议:
1.JMS基于jvm消息代理规范,常见的ActiveMQ
2.AMQP:高级消息队列协议,兼容JMS,常见rabbitMQ

各个协议的优点:
1.JMS基于java,实现面向接口编程,导入不同实现类即可
2.amqp不仅仅局限于java,是网络协议

以下基于rabbitMq说明。
在这里插入图片描述

使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

消息队列常见问题

在这里插入图片描述

1.消息丢失

1.开启rabbitmq事务模式,但性能下降250倍
2.引入消息确认机制,publish->exchange->queue->consumer,三个箭头分别解决
1.ConfirmCallback,broker刷盘消息后返回确认。
2.ReturnCallback,只要消息没有投递给指定的队列,就触发这个失败回调
3.ack

但是引入回调策略,必然会有几率导致消息重复的问题。
因为,任何一个接收端接受消息后,如果没有确认返回,发送端再次发送,就导致了消息重复问题

2.消息重复

从上面可知,消息重复无法避免,但是可以在应用层解决重复消费问题。
也就是保证接口幂等性
那么如何保证接口幂等性呢。

1.应用层实现:token令牌机制
例如:上架商品时,给每一个商品设置一个唯一token,保存在redis中。
当consumer接收到消息时,比较消息内的token和redis中的。最后删除token就行。
问题:但是比较token和删除token的先后顺序会出现问题。
解决:使用redis配合Lua脚本保证token校验和删除的原子性

2.数据库实现,redis实现
1)乐观锁
例:update table_name set version = version + 1 where version = 0;
2)悲观锁
3)唯一性索引或者防重表
4)基于redis的分布式锁
2,3只能保证插入,不能完全保证更新操作

3.消息积压

情况:
1.消费者宕机积压
2.消费者消费能力不足积压
3.发送者发送流量太大

1.上线更多的消费者,进行正常消费(用于平时,因为消费能力必须比生产强)
2.上线专门的队列消费服务,将消息先批量取出来,记录数据库,离线慢慢处理(用于比如双十一)

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐