随手记点笔记,不全,自用

本文思维导图(xmind)

优势

应用解耦

  • MQ 作为各系统的中间件,使系统的代码最大程度上解耦,后期修改各功能方便

异步提速

  • MQ 作为系统间的中间件,可以异步运行,各系统间隔离,提升运行速度

削峰填谷

  • MQ 作为中间件,缓冲大量请求,子系统后续进行拉取

劣势

系统可用性降低

  • 分布式系统引入的外部依赖变多(增加了 MQ 系统),系统稳定性变差,一旦 MQ 宕机,会对业务造成影响

系统复杂度提高

  • 异步调用 MQ 需要保证消息没有被重复消费,消息没有丢失,消息传递的顺序不紊乱

一致性问题

  • MQ 的消息在后续不同系统中处理结果不一致的情况

高级特性

消息的可靠投递

  • confirm

    • ConnectionFactory 中开启 publisher-confirms=“true”

    • rabbitTemplate 中定义 ConfirmCallBack 回调函数

      • rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback){
        @Override
        public void confirm(){}
        }
  • return

    • ConnectionFactory 中开启 publisher-return=“true”

    • 定义 ReturnCallBack 同上

    • 设置 Exchange 处理消息的模式

      • 如果消息没有路由到 Queue,则丢弃消息(默认)
      • 如果消息没有路由到 Queue,返回消息给发送方 ReturnCallBack

Consumer Ack

  • listener-container 中设置属性 acknowledge=“manual”
  • 让监听器类实现 ChannelAwareMessageListener 接口
  • 如果消息处理成功,则调用 channel 的 basicAck()签收
  • 如果消息处理失败,则调用 channel 的 basicNack()拒绝签收,broker 重新发送给 consumer

消费端限流

  • 确保 ack 机制为手动确认
  • listener-container 配置属性 perfetch = n,表示消费端每次从 mq 拉取 n 条消息来消费,直到手动确认消费完毕后,才会继续拉取下一批消息

TTL

  • 统一过期:
    rabbit:queue 中设置 queue-arguments
  • 消息单独过期:
    使用 MessagePostProcessor 对象的 postProcessMessage 方法处理 Message 对象,message.getMessageProperties().setExpiration(“5000”)

死信队列 DLX

  • x-dead-letter-exchange

  • x-dead-letter-routing-key

  • 消息成为死信的三种情况

    • 队列消息长度到达限制
    • 消费者拒接消息,并且不重回队列
    • 原队列存在消息过期设置,过期未被消费

延迟队列(TTL+DLX)

消息补偿

  • 延时发送一个消息,增加一个回调服务进行数据对比来检漏,并增加一个定时服务定期检漏以防延时消息也没发送成功

消息幂等性保障

  • 消费多条同样的消息结果应为消费一次(比如重复扣费问题)

  • 解决方法(乐观锁)

    • 表中添加 version 字段
    • 执行更新操作前查询 version
    • 执行更新语句,以查到的 version 作为条件,比如
      UPDATE XXX SET VERSION=VERSION+1 WHERE VERSION=1
    • 如果执行更新时有其他人先更新了,则当前操作就不会执行了

集群

  • 负载均衡 HAProxy