ActiveMQ的集群与高可用
针对大量的消息吞吐量、对MQ可用性要求非常严格的场景、或者非常复杂的消息处理关系情况下,单个MQ实例通常已经无法满足我们的需要,这时候ActiveMQ的集群和高可用方案就对我们很重要了。
1.client的集群
对消费者来说,使用queue即可做到某种意义上的消费者集群,所有消费者共同处理同一类消息。
非持久订阅的topic,这种功能没有实现。但是持久订阅的topic,可以通过Composite Destination机制转换成针对具体的持久消费者的专用queue,从而实现多个client共同处理同一类消息。参见:http://blog.csdn.net/kimmking/article/details/9773085
需要注意的是,如果缓存了consumer(例如spring DMLC+cache consumer)情况下使用了prefetch,多个consumer间可能导致消息顺序混乱。见:http://activemq.apache.org/what-is-the-prefetch-limit-for.html
2.client的高可用
在客户端来说,最简单的高可用方案就是内置的failover机制。它帮助我们在客户端实现:
- 在某个broker故障时,自动使用其他备用broker
- 强大的断线重连机制,哪怕是只有一个broker时,也可以用来在broker down掉重启后,客户端重新连接上
断线重连的配置和参数说明参见:http://activemq.apache.org/failover-transport-reference.html
3.broker的集群
broker端,典型的集群方式就是Network Connector,通过桥接的方式把多个broker,一个个的串起来,整个broker网络就可以作为一个整体,协同工作。
每个connect上去的broker,都会自动在被连接的broker上创建一个client connecttion,并通过Advisory机制共享自己的消费者列表,从而使得消息可以跨过broker在这个网络上自由流动。也可以设置duplex为true使得这个连通变为双向的对等网络。在BrokerA上配置一个指向BrokerB上的network connector,则连接到BrokerA上的各个ConsumerA1、ConsumerA2、ConsumerA3,都可以消费BrokerB上的QueueB里的消息。默认这三个消费者都被当做一个消费者来看待,即如果BrokerB上有一个ConsumerB1消费。
详细参见:http://blog.csdn.net/kimmking/article/details/8440150
其实个人感觉更好的集群方式是增加类似kafka和metaq的partition,然后使用zk作为配置中心来协调各个不同的broker实例、以及不同的partition来协同工作,使得broker的读写都可以分散进行。
4.broker的高可用
Broker端的高可用主要是Master-Slave实现的冷备,需要结合客户端的failover来用。
5.8.0以前的版本,支持三种Master-Slave:
- 基于共享储存的Master-Slave:多个broker实例使用一个存储文件,谁拿到文件锁就是master,其他处于待启动状态,如果master挂掉了,某个抢到文件锁的slave变成master。由于使用的还是master的存储文件,所以数据好似一致的。
- 基于JDBC的Master-Slave:使用同一个数据库,拿到LOCK表的写锁的broker成为master,机制同上。
- Pure Master-Slave:Slave的broker,简单的从Master复制数据和状态,问题较多,已被废弃。
5.9.0版本以后,Pure Master-Slave机制被废弃,新添加了基于zk的复制LevelDB存储Master-Slave机制。
此外还有一种可选方式就是,使用某种存储复制技术,比如Raid、或是DB的replication等等机制来同步存储,在故障的时候,使用这个复制的存储恢复broker。