消息队列的exclusive consumer功能是如何保证消息有序和防止脑裂的

一般来说,消息队列都会保证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。这样我们就保证队列中的消息是被顺序消费的。

时间: 2024-08-01 17:41:46

消息队列的exclusive consumer功能是如何保证消息有序和防止脑裂的的相关文章

RabbitMQ消息队列(六):使用主题进行消息分发

         在上篇文章RabbitMQ消息队列(五):Routing 消息路由 中,我们实现了一个简单的日志系统.Consumer可以监听不同severity的log.但是,这也是它之所以叫做简单日志系统的原因,因为是仅仅能够通过severity设定.不支持更多的标准.         比如syslog unix的日志工具,它可以通过severity (info/warn/crit...) 和模块(auth/cron/kern...).这可能更是我们想要的:我们可以仅仅需要cron模块的l

EQueue - 一个C#写的开源分布式消息队列的总体介绍

前言 本文想介绍一下前段时间在写enode时,顺便实现的一个分布式消息队列equeue.这个消息队列的思想不是我想出来的,而是通过学习阿里的rocketmq后,自己用c#实现了一个轻量级的简单版本.一方面可以通过写这个队列让自己更深入的掌握消息队列的一些常见问题:另一方面也可以用来和enode集成,为enode中的command和domain event的消息传递提供支持.目前在.net平台,比较好用的消息队列,最常见的是微软的MSMQ了吧,还有像rabbitmq也有.net的client端.这

ActiveMQ消息队列

什么是MQ? 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术(如:WebService).排队指的是应用程序通过队列来通信.队列的使用除去了接收和发送应用程序同时执行的要求. 为什么要用MQ? 1.调用异步化,提高服务器性能 在不使用消息队列的情况下,用户的请求数据直接写入数据库,

大型网站架构系列:消息队列(二) (转)

本文是大型网站架构系列:消息队列(二),主要分享JMS消息服务,常用消息中间件(Active MQ,Rabbit MQ,Zero MQ,Kafka).[第二篇的内容大部分为网络资源的整理和汇总,供大家学习总结使用,最后有文章来源] 本次分享大纲 消息队列概述(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息队列应用场景(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息中间件示例(见第一篇:大型网站架构系列:分布式消息队列(一)) JMS消息服务 常用消息队列 参考(推荐)资料 本

System V 消息队列

1.概述 消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识.具有足够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息.在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达.System V 消息队列是随内核持续的,只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除.可以将内核中的某个特定的消息队列画为一个消息链表,如下图所示: 对于系统中没个消息队列,内核维护一个msqid

消息队列在VB.NET数据库开发中的应用

数据|数据库 我们先简单的了解一下什么是消息队列(MSMQ)?消息队列是 Windows 2000(NT也有MSMQ,WIN95/98/me/xp不含消息队列服务但是支持客户端的运行)操作系统中通讯的基础,也是用于创建分布式.松散连接通讯应用程序的工具.这些应用程序可以通过不同种类的网络进行通讯,也可以与脱机的计算机通讯.消息队列分为用户创建队列和系统队列,用户队列分为: · "公共队列"在整个可传递消息的"消息队列"网络中复制并传输,并且有可能由网络连接的所有站点

enode框架入门:消息队列的设计思路

上一篇文章,简单介绍了enode框架内部的整体实现思路,用到了staged event-driven architecture的思 想.通过前一篇文章,我们知道了enode内部有两种队列:command queue.event queue:用户发送的command 会进入command queue排队,domain model产生的domain event会进入event queue,然后等待被dispatch到所 有的event handlers.本文介绍一下enode框架中这两种消息队列到底

linux网络编程之POSIX消息队列和系列函数

一.在前面介绍了system v 消息队列的相关知识,现在来稍微看看posix 消息队列. 其实消息队列就是一个可 以让进程间交换数据的场所,而两个标准的消息队列最大的不同可能只是api 函数的不同,如system v 的系列函数是 msgxxx,而posix 是mq_xxx.posix 消息队列也有一些对消息长度等的限制,man 7 mq_overview: simba@ubuntu:~/Documents/code/linux_programming/UNP/posix$ cat /proc

PHP高级编程之消息队列

PHP高级编程之消息队列 http://netkiller.github.io/journal/php.mq.html Mr. Neo Chen (陈景峰), netkiller, BG7NYT 中国广东省深圳市龙华新区民治街道溪山美地518131+86 13113668890+86 755 29812080<netkiller@msn.com> 版权声明 转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明. 文档出处: http://netkiller.github.io ht