分布式三大利器之《消息队列》
消息队列作用1.异步处理(无需同步阻塞,给予用户体验)2.应用解耦(远程调用一方改变接口,另一微服务必须同时改写源代码)3.流量削峰(防止百万流量冲击服务器,防止宕机)两种模式1.点对点(队列,多个人监听,只有一个人能接收消息)2.发布订阅模式(多个人可以同时接收消息)协议消息队列遵循的协议:1.JMS基于jvm消息代理规范,常见的ActiveMQ2.AMQP:高级消息队列协议,兼容JMS,常见r
消息队列
作用
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.上线专门的队列消费服务,将消息先批量取出来,记录数据库,离线慢慢处理(用于比如双十一)
更多推荐
所有评论(0)