一. 可靠性保证
1.1 发送消息可靠性保证
rabbitmq 提供监听器来接受消息传递的状态,包括confirm和return两种。
- confirm 代表消息是否成功送到broker的状态
- return 代表消息被broker正常接收后,但broker没有找到对应的接收者的状态。即没有任何消费者消费这个消息。
//开启confirm监听模式
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long l, boolean b) throws IOException {
//第二个参数代表接收的数据是否为批量接收,一般我们用不到。
System.out.println("消息已被Broker接收,Tag:" + l );
}
public void handleNack(long l, boolean b) throws IOException {
System.out.println("消息已被Broker拒收,Tag:" + l);
}
});
channel.addReturnListener(new ReturnCallback() {
public void handle(Return r) {
System.err.println("===========================");
System.err.println("Return编码:" + r.getReplyCode() + "-Return描述:" + r.getReplyText());
System.err.println("交换机:" + r.getExchange() + "-路由key:" + r.getRoutingKey() );
System.err.println("Return主题:" + new String(r.getBody()));
System.err.println("===========================");
}
});
1.2 持久化
- exchange 持久化,exchange创建时持久化
- queue 持久化 ,queue创建时持久化
- message 持久化,消息发送时指定持久化
1.3 消费确认
rabbmitmq 提供Consumer Ack机制来保证消费可靠性。ack指Acknowledge,确认。 表示消费端收到消息后的确认方式。有三种确认方式:
- 自动确认:acknowledge="none"
当消息一旦被Consumer接收到,则自动确认收到,并将相应 message 从 RabbitMQ 的消息缓存中移除。但是在实际业务处理中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失。
- 手动确认:acknowledge="manual"
设置了手动确认方式,则需要在业务处理成功后,调用channel.basicAck(),手动签收,如果出现异常,则调用channel.basicNack()方法,让其自动重新发送消息。
- 根据异常情况确认:acknowledge="auto",(这种方式使用麻烦,不作讲解)
1.4 broker 高可用
rabbitmq 支持高可用集群部署。后续介绍。
二. 特性功能
2.1 限流
1.通过prefetch属性设置消费端一次拉取多少消息,极限每次一个。
2.设置ack模式为手动
2.2 TTL
TTL 全称 Time To Live(存活时间/过期时间)。
当消息到达存活时间后,还没有被消费,会被自动清除。
RabbitMQ可以对消息设置过期时间,也可以对整个队列(Queue)设置过期时间。
设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
设置消息过期时间使用参数:expiration。单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。
如果两者都进行了设置,以时间短的为准
2.3 死信队列
死信队列,英文缩写:DLX 。Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。
消息成为死信的三种情况:
队列消息长度到达限制;
消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false;
原队列存在消息过期设置,消息到达超时时间未被消费;
实现原理
给队列设置参数: x-dead-letter-exchange 和 x-dead-letter-routing-key, 来绑定死信交换机。死信交换机和普通的没有区别。
当消息成为死信后,如果该队列绑定了死信交换机,则消息会被死信交换机重新路由到死信队列。
指定一个消费者消费私信队列消息。
2.4 延迟队列
rabbitmq 并没有直接提供延迟队列功能,而是通过TTL和死信队列来达到延迟队列的目的。
- 通过TTL的到期实践来实现延迟时间。
- 不设置任何消费者,当到达延迟时间时,让消息走入私信队列
- 直接监听私信队列消息,实现延迟执行
三. 镜像集群
用 KeepAlived 做 HA-Proxy 的高可用,然后有 3 个节点的 MQ 服务,消息发送到主节点上,主节点通过 mirror 队列把数据同步到其他的 MQ 节点,这样来实现其高可靠。