在上一节[url=http://flyingdutchman.iteye.com/admin/blogs/1911811]《RabbitMQ集群类型一:在单节点上构建built-in内置集群》[/url]中我们已经学习过:在集群环境中,队列只有元数据会在集群的所有节点同步,但队列中的数据只会存在于一个节点,数据没有冗余且容易丢,甚至在durable的情况下,如果所在的服务器节点宕机,就要等待节点恢复才能继续提供消息服务。
那么是不是有消息冗余的解决方案呢?这就要提到从RabbitMQ 2.6.0版本开始提供支持 [b]镜像队列(Mirrored Queue)[/b],消息会在rabbitmq节点之间的被创建为“镜像队列”的队列之间复制。和其它的主从设计一样,镜像队列也有master和slave的概念,一旦某个节点当掉,会在其余的节点中选举一个slave作为master。

在镜像队列(Mirrored Queue)中,只有master的copy对外提供服务,而其他slave copy只提供备份服务,在master copy所在节点不可用时,选出一个slave copy作为新的master继续对外提供服务。

之前我们也将过,rabbitmq会同过一种“选举”机制在余下的所有的salve中选出一个

[b]理想总是简单,真实却总是复杂。[/b]如果我们要在运行时添加一个新的节点到集群中,消息复制会怎么处理?如果有新节点加入,RabbitMQ不会同步之前的历史数据,新结点只会复制该结点加入到集群之后新增消息.这里的假设是随着消息的被consumer取走,最终所有的节点的数据都会对齐一致。
接下来,一个自然的追问就“诞生”了:既然master节点退出集群会选一个slave作为master,那么如果不幸选中了一个刚刚加入集群的节点怎么办?那消息不就丢了吗!?这里您可以把心放到您的肚子里,RabbitMQ集群内部会维护节点的状态是否已经同步,使用rabbitmqctl的synchronised_slave_pids参数,就可以查看状态.如果slave_pids和synchronised_slave_pids里面的节点是一致的,那说明全都同步了.如果不一致很容易比较出来哪些还没有同步,[b]集群只会在“最老”的slave节点之间选一个出来作为新的master节点。[/b]

镜像队列分为两种:集群内全节点复制的镜像队列和集群内局部节点复制的镜像队列。先面我们就看一下如何创建镜像队列Mirrored Queue:其实很简单,只要在创建消息队列时,添加一个叫“x-ha-policy”的key/value对就可以了:[quote]
[color=blue]//创建集群内全节点复制的镜像队列
...
queue_args = {'x-ha-policy' : 'all'}
channel.queue_declare(queue = 'hello-queue',arguments = queue_args)
...[/color]

[color=indigo]//创建集群内局部节点复制的镜像队列
...
queue_args = {'x-ha-policy' : 'nodes',
'x-ha-policy-params' : [rabbit@JackyChen,rabbit3@JackyChen]}
channel.queue_declare(queue = 'hello-queue',arguments = queue_args)
...[/color]
[/quote]

下面我们通过实际的python代码并执行相关的操作来验证一下镜像队列:[quote]
[color=blue]# mkdir -p /data/rabbitmq-pika/c5
# cd /data/rabbitmq-pika/c5
# touch hello_world_mirrored_producer.py
# chmod +x hello_world_mirrored_producer.py
# touch hello_world_mirrored_consumer.py
# chmod +x hello_world_mirrored_consumer.py[/color]
[/quote]
其中hello_world_mirrored_producer.py代码如下:[quote]
#!/usr/bin/env python
#coding=utf-8

import pika,sys
from pika import spec

#在"/"虚拟主机vhost上通过用户guest建立channel通道
user_name = 'guest'
user_passwd = 'guest'
target_host = 'JackyChen'
vhost = '/'
cred = pika.PlainCredentials(user_name,user_passwd)
conn_params = pika.ConnectionParameters(target_host,
virtual_host = vhost,
credentials = cred)
conn_broker = pika.BlockingConnection(conn_params)
channel = conn_broker.channel()

#创建一个direct类型的、持久化的、没有consumer时队列是否自动删除的exchage交换机
channel.exchange_declare(exchange = 'hello-exch',
type = 'direct',
passive = False,
durable = True,
auto_delete = False)

#使用接收到的信息创建消息
msg = sys.argv[1]
msg_props = pika.BasicProperties()
msg_props.content_type = 'text/plain'
#持久化消息
msg_props.delivery_mode = 2
msg_ids = []

print 'ready to publish...'
#发布消息
channel.basic_publish(body = msg,
exchange = 'hello-exch',
properties = msg_props,
routing_key = 'hala')
print 'published!'
msg_ids.append(len(msg_ids) + 1)
print len(msg_ids)
channel.close()
conn_broker.close()
[/quote]
hello_world_mirrored_consumer.py代码如下:[quote]
#!/usr/bin/env python
#coding=utf-8

import pika

#在"/"虚拟主机vhost上通过用户guest建立channel通道
user_name = 'guest'
user_passwd = 'guest'
target_host = 'JackyChen'
vhost = '/'
cred = pika.PlainCredentials(user_name,user_passwd)
conn_params = pika.ConnectionParameters(target_host,
virtual_host = vhost,
credentials = cred)
conn_broker = pika.BlockingConnection(conn_params)
conn_channel = conn_broker.channel()

#创建一个direct类型的、持久化的、没有consumer时,队列是否自动删除exchage交换机
conn_channel.exchange_declare(exchange = 'hello-exch',
type = 'direct',
passive = False,
durable = True,
auto_delete = False)

#创建一个持久化的、没有consumer时队列是否自动删除的名为“hello-queue”
#创建集群内全节点复制的镜像队列
queue_args = {'x-ha-policy' : 'all'}
#创建集群内局部节点复制的镜像队列
#queue_args = {'x-ha-policy' : 'nodes','x-ha-policy-params' : ['rabbit@JackyChen','rabbit3@JackyChen']}
conn_channel.queue_declare(queue = 'hello-queue',
durable = True,
auto_delete = False,
arguments = queue_args)

#将“hello-queue”队列通过routing_key绑定到“hello-exch”交换机
conn_channel.queue_bind(queue = 'hello-queue',
exchange = 'hello-exch',
routing_key = 'hala')

#定义一个消息确认函数,消费者成功处理完消息后会给队列发送一个确认信息,然后该消息会被删除
def ack_info_handler(channel,method,header,body):
"""ack_info_handler """
print 'ack_info_handler() called!'
if body == 'quit':
channel.basic_cancel(consumer_tag = 'hello-hala')
channel.stop_sonsuming()
else:
print body
channel.basic_ack(delivery_tag = method.delivery_tag)

conn_channel.basic_consume(ack_info_handler,
queue = 'hello-queue',
no_ack = False,
consumer_tag = 'hello-hala')

print 'ready to consume msg...'
conn_channel.start_consuming()
[/quote]

打开rabbitmq集群中所有节点:[quote]
[color=blue]# /opt/mq/rabbitmq/sbin/rabbitmqctl start_app
# /opt/mq/rabbitmq2/sbin/rabbitmqctl start_app
# /opt/mq/rabbitmq3/sbin/rabbitmqctl start_app[/color]
[/quote]
然后执行:[quote]
# ./hello_world_mirrored_consumer.py
# ./hello_world_mirrored_producer.py
[/quote]

[color=red][b]注意:[/b][/color]上面是rabbitmq 3.0之前的创建镜像队列的方法,3.0之后改为通过[quote]
[color=blue]//给所有以“hello”开头为名创建的消息队列设置为集群内全节点复制的镜像队列
# ./rabbitmqctl set_policy ha-all2 "^hello.*" '{"ha-mode":"all"}'[/color]
[/quote]
[img]http://dl2.iteye.com/upload/attachment/0087/3345/7fe75059-2088-309d-ba26-3996b64c2fe3.jpg[/img]
创建集群内局部节点复制的镜像队列:[quote]
[color=blue]
# ./rabbitmqctl set_policy ha-all "^halo.*" '{"ha-mode":"nodes","ha-params":["rabbit@JackyChen","rabbit3@JackyChen"]}'[/color]
[/quote]
[img]http://dl2.iteye.com/upload/attachment/0087/3347/8533cc96-0a36-3fe9-9aed-74df8cee6456.jpg[/img]
另外还有一种的镜像队列:[quote][color=blue]
//只指定在整个集群节点中只包含count = n 个镜像的镜像列表
# ./rabbitmqctl set_policy ha-all3 "^alert.*" '{"ha-mode":"exactly","count":2}'[/color]
[/quote]

RabbitMQ:镜像队列Mirrored queue相关推荐

  1. [Erlang 0090] RabbitMQ 集群: Mirrored Queue

    之前提到过在集群环境中,队列只有元数据会在集群的所有节点同步,但是队列中的数据只会存在于一个节点;这不免让人失望:数据没有冗余容易丢数据甚至在durable的情况下,如果所在的节点当掉就要等待节点恢复 ...

  2. RabbitMQ + 镜像队列 + HAProxy 实现负载均衡的集群

    RabbitMQ + 镜像队列 + HAProxy 实现负载均衡的集群 一.集群管理(RabbitMQ扩容) 1. 环境介绍 hostname ip mq1 192.168.80.16 mq2 192 ...

  3. RabbitMQ镜像队列原理分析

    对于RabbitMQ的节点来说,有单节点模式和集群模式两种,其中集群模式又分为普通集群模式和镜像队列集群模式,在<RabbitMQ集群架构搭建与高可用性实现>文中,介绍了RabbitMQ的 ...

  4. rabbitmq——镜像队列

    转自:http://my.oschina.net/hncscwc/blog/186350?p=1 1. 镜像队列的设置 镜像队列的配置通过添加policy完成,policy添加的命令为: rabbit ...

  5. RabbitMQ镜像队列与负载均衡

    镜像队列 RabbitMQ集群是由多个broker节点构成的,那么从服务的整体可用性上来讲,该集群对于单点失效是有弹性的,但是同时也需要注意:尽管exchange和binding能够在单点失效问题上幸 ...

  6. RabbitMQ镜像队列实现原理

    一.镜像队列使用 1.镜像队列作用 ​ RabbitMQ默认集群模式,并不包管队列的高可用性,尽管队列信息,交换机.绑定这些可以复制到集群里的任何一个节点,然则队列内容不会复制,固然该模式解决一项目组 ...

  7. ActiveMQ 镜像队列Mirrored Queues

    概述 ActiveMQ中每个queue中的消息只能被一个consumer消费.然而,有时候你可能希望能够监视生产者和消费者之间的消息流.你可以通过使用Virtual Destinations 来建立一 ...

  8. RabbitMQ之镜像队列

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  9. Rabbitmq集群,镜像队列和分布式原理

    前言 基于前两次的分享会,结合rabbitmq相关知识,做一个小结.说明一致性的设计思想,在此说明相关的基础理论. CAP定理: 在计算机科学里,CAP定理又被称作布鲁尔定理(Brewer theor ...

最新文章

  1. MySQL-数据库监控初探
  2. 发那科机器人寄存器Ar_发那科机器人与TP参数的千丝万缕关系
  3. 解决NHibernate 中与 SQL2005 关键字有冲突的问题
  4. 【剑指offer】面试题25:合并两个排序的链表(Java 实现)
  5. 四川大学计算机专业贵州分数线,四川大学2016年在贵州省高考各专业录取分数线...
  6. 国内最全最详细的hadoop2.2.0集群的HA高可靠的最简单配置
  7. dd命令打包多个文件_linux下如何tar打包多个并列文件夹,如:将a文件夹 b文件夹 c文件夹,打包成d.tar文件...
  8. Mac电脑清空搜狗输入法联想记忆词库
  9. 工商阿里忙互殴 苏宁高调打假争做主角?
  10. 从Ping-Pong消息学习Gossip协议
  11. 开源免费cms---十大主流建站的CMS系统介绍
  12. springboot+ssm+vue前后端分离项目-宠物之家
  13. 最简易的Cfree代码,cfree爱心代码。
  14. 【机器学习】如何理解vias和bias?
  15. Java--面包师与消费者1(发送与接收线程)
  16. 计算机微课有哪些类型如何应用,微课在大学计算机基础教学中的应用
  17. 天津市“多规合一”信息资源目录体系建设
  18. SnapKit安装与使用
  19. R语言用WinBUGS 软件对学术能力测验建立层次(分层)贝叶斯模型
  20. 维刻官方正品防伪系统升级公告

热门文章

  1. 谈笑间学会数仓—主题域数据域
  2. 史诗级梦境之二:沙漠大逃亡
  3. ThinkPHP6.0 Session 问题
  4. 音乐flac格式如何快速简单的转换为mp3格式
  5. 计算机组装原则与注意事项,计算机安装流程和注意事项
  6. 计算机专业买电脑买那种好,windows7好还是windows10好_电脑系统7和10哪个好用
  7. 程序员的算法趣题Q50: 完美洗牌
  8. 【2021】Structure-Preserving Deraining with Residue Channel Prior Guidance
  9. AngularJS(2)——AngularJS数据双向绑定
  10. origin处理多组红外数据_【图文】用Origin作多组红外数据图