延迟队列实现原理 a. 死信的来源 ⅰ. 消息 TTL 过期 ⅱ. 队列已经达到了最大长度(队列满了,无法添加消息到 MQ 中) ⅲ. 消息被拒绝 b. 延迟队列:不就想要消息延迟多久被处理,TTL 则刚好能让消息在延迟多久之后成为死信,成为死信的消息都会被投递到死信队列里,这样只需要消费者一直消费死信队列里的消息就完事了,因为里面的消息都是希望被立即处理的消息 c. 存在的问题: ⅰ. RabbitMQ 只会检查第一个消息是否过期,过期则投递到死信队列中, ⅱ. 如果第一消息的延时时长很长,而第二个消息的延时时长很短,第二个消息并不会优先得到执行 d. 引入RabbitMQ 插件实现延迟队列 ⅰ. x-delayed-message,该类型消息支持延迟投递机制,消息传递后并不会立即投递到目标队列中,而是存储在 mnesia(一个分布式数据系统)表中,当达到投递时间时,才投递到目标队列中
消息怎么防止丢失? a. 如果 RabbitMQ 因为自身内部错误导致消息丢失,就会发送一条 nack 消息,生产者应用程序同样可以在回调方法中处理该 nack 消息 b. 消息自动重新入队,如果消费者由于某些原因失去连接,导致消息未发送 ACK 确认,RabbitMQ 将会把该消息重新入队,重新分发给另一个消费者
消息怎么防止重复消费?
交换机有几种 a. 默认的交换机 b. Fanout,类似广播,将接收到的所有消息广播到他所知道的队列中 c. Direct,消息只去到他绑定的 routingkey 队列中去 d. Topics,相比 Fanout 和 Direct 来说比较灵活,可以动态配置同一组下的队列
发布确认 a. 单个发布确认,同步确认发布方式,发布一个消息之后只有他被确认发布,后续消息才可以被发布 ⅰ. 发布速度特别慢,如果没有确认发布的消息就会阻塞所有后续消息的发布 b. 批量确认发布,同步发布一批消息后,再一起确认,之后消息才可以继续发布 ⅰ. 发生故障时,不知道是哪个消息出现问题,必须将整个批量保存在内存中,以记录重要的信息之后重新发布 c. 异步确认发布, ⅰ. 处理逻辑比单笔和批量复杂,但是性价比高 ⅱ. 使用回调函数来达到消息可靠性传递的,这个中间件也是通过函数回调来保证是否投递成功
队列持久化,如何保证服务停掉之后,消息生产者发送过来的消息不会丢失? a. 默认情况下,RabbitMQ 退出或者由于某种原因奔溃时,他会忽视队列和消息 b. 确保消息不会丢失需要做两件事:需要将队列和消息都标记为持久化 c. 如果之前的队列是非持久化的,rabbitMQ 重启,队列就会被删除,如果要队列实现持计划,需要在声明队列时把 durable 参数设置为持久化
消息持久化 a. 要想消息持久化,需要在消息生产者修改代MessageProperties.PERSISTENT_TEXT_PLAIN 添加这个属性
消息分发 a. 不公平分发 b. 预取值,限制此缓冲区大小,以避免缓冲区里面无限制的未确认消息问题,该值定义通道上允许的未确认消息的最大数量
消息应答,消费者在接收到消息并处理该消息后,告诉 rabbitMQ 他已经处理了,可以把该消息删除了 a. 自动应答 b. 手动应答 c. 消息自动重新入队,如果消费者由于某些原因失去连接,导致消息未发送 ACK 确认,RabbitMQ 将会把该消息重新入队,重新分发给另一个消费者
RabbitMQ 原理 a. 本质上是一个队列,只不过队列中存放的内容是消息,是一种跨进程的通信机制,用于上下游传递消息 b. 为什么要用MQ ⅰ. 应用解耦、异步处理,除异步处理外还有(流量削峰) c. 性能较好、功能比较完备、稳定、易用、跨平台、支持多语言、文档比较全 d. 界面管理方便,适用于业务数数据量没有那么大