博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
消息队列的exclusive consumer功能是如何保证消息有序和防止脑裂的
阅读量:6261 次
发布时间:2019-06-22

本文共 1376 字,大约阅读时间需要 4 分钟。

一般来说,消息队列都会保证queue当中的消息的顺序。然而如果有多个consumer同时消费同一个queue,那么这时就不能保证的消息的顺序性。

有时候,消息的顺序是非常重要的,为了能顺序的消费消息,我们只能启动一个consumer来消费这个queue。但是这样做的问题就是,如果这个consumer宕调了话,消息就不能得到处理了,consumer的可用性不能得到保证。

那么如何提高consumer的可用性那,通常的做法是启动多个consumer,让其中一个consumer成为master,其他的为slave,成为master的consumer才去消费queue中的消息(通常的做法是使用zookeeper进行选主)。

但是这仍然没有解决全部问题。假设master在要消费一条消息之前,发生了一次很长的gc(假设我们是一个java的程序,当然也有其他的导致这个问题的场景),zookeeper认为master挂了,重新选主,一个slave被提升为master,并且开始消费这个queue的消息,这时原来的master从gc中恢复,在一定的时间范围内,原master还没有收到zookeeper通知它已经不是主了,这时它会继续消费queue中的消息。也就是说,在这段时刻,我们有2个认为自己是master的consumer。这种现象是分布系统中所说的脑裂。Zookeeper可以用来选主,zookeeper会保证只选出一个主,但是zookeeper并不能保证在某一时间系统中只有一个主,也就是说用了zookeeper并不能保证脑裂不会发生。Zookeeper不是用来防止脑裂的。

那么如何解决这问题那?很多mq都有exclusive consumer的概念,我们可以用它来解决这个问题。首先我们来说一下,什么是exclusive consumer。

拿activemq来说,我们在创建queue时,可以指定这个queue是exclusive,比如

queue = new ActiveMQQueue("TEST.QUEUE?consumer.exclusive=true");

如果一个queue设置为exclusive,broker会调选一个consumer,并且将所有的消息都发给这个consumer。如果这个consumer挂了,broker会自动挑选另外一个consumer。

对于rabbitmq来说,有2个exclusive参数可以设置:第一个是declare一个queue时可以指定exclusive=ture(也即queue_declare方法),那么这个queue只能被当前连接访问,当连接断开时queue会被删除。也可以这么理解exclusive queue是私有queue,non-exclusive queue是共享queue。第二个是consumer一个queue时可以指定exclusive=ture(也即basic_consume),那么这个queue只能被这个consumer访问。

脑裂问题我们是不能避免的,可以避免的时在发生脑裂时,2个master能同时去消费queue中的数据。所以我们应该用zookeeper来选主,让主去消费队列,并且队列要设置成exclusive。这样我们就保证队列中的消息是被顺序消费的。

转载地址:http://hdesa.baihongyu.com/

你可能感兴趣的文章
Android基础 四大组件之广播(Broadcast)
查看>>
SQL优化器原理 - 查询优化器综述
查看>>
微服务架构 vs SOA架构
查看>>
maven项目注意
查看>>
Git学习分享
查看>>
阿里云移动端播放器高级功能---画面控制
查看>>
Ethereum地址是如何生成的
查看>>
峰采 #2
查看>>
高阶组件之属性代理
查看>>
Python 比特币 教程 之一:创建机器人
查看>>
extract-text-webpack-plugin用法
查看>>
java中的多线程你只要看这一篇就够了
查看>>
利用tornado实现表格文件预览
查看>>
深入call apply bind
查看>>
「前端面试题系列6」理解函数的柯里化
查看>>
用友云开发者中心助你上云系列之在线调试
查看>>
【跃迁之路】【724天】程序员高效学习方法论探索系列(实验阶段481-2019.2.14)...
查看>>
个人博客四|注册登录退出功能后台开发
查看>>
工作中常用到的ES6语法
查看>>
Django-Signals信号量
查看>>