消息队列是如何保证高可用的?redis
已RocketMQ为例:数据库
NameServer相似于kafka的zk,起到master和slave的注册和发现。 Producer和NameServer集群的随机一点创建长连接,按期从NameServer获取Topic路由信息,并向Topic服务的Broker Master创建长连接,且定时向Broker发送心跳。网络
Producer发送消息到Broker master,Consumer能够从Topic的Master和Slave的broker订阅消息。架构
对比看下kafka的架构图: 异步
经过zk管理集群配置,选举leader及对consumer group进行rebalance。 consumer能够采用pull和push方式订阅消息。blog
RabbitMq能够经过普通集群和镜像模式进行可用性保证。队列
不一样的MQ有不一样的消费机制,ack以后消息会从消息队列中删除。 形成重复消费的缘由可能有如下几点:事务
业务上的解决:路由
可靠性从如下几个调度考虑:kafka
RabbitMq的transaction机制,在发送消息以前,开启事务,而后发送消息,若是出现异常进行回滚,发送成功执行commit。
信道发出去的消息会被指派一个惟一ID,消息路由到队列后,队列会返回Ack信息其中包含惟一ID,打到确认目的,若是没能处理此消息,会返回NAck,以后进行重试操做。
队列为防止丢数据,通常开启磁盘持久化,能够在confirm持久化磁盘后返回ack,这样保证了消息的持久化。
消费者能够采用自动确认模式,确认后当即删除,为解决丢失数据后,重复消费,能够关闭自动确认,采用手动确认。
producer发送消息到partition后,经过zk找到partition的leader,leader写入本地log,follower主动从leader来pull数据。
能够配置produder的acks=all,这样须要follower同步后才确认消息发送成功。 producer设置retries=MAX,写入失败后会进入无限重试。
为保证zk切换leader过程当中数据丢失,能够配置replication.factor,即设置副本数量,要求每一个partition必须至少2个副本。min.insync.replicas,是leader须要感知至少多少个follower和本身保持联系。
kafka消费主要依赖于offset,每一个消费组消费的消息都有惟一的offset下标,消费者消费后提交offset。
业务上通常没有这类需求,通常能够采用将消息放到一个信道里面,kafka的partiton,rabbitMq的queue,而后控制消费者顺序消费。