RabbitMQ高可用

RabbitMQ高可用

  • 各种消息队列对比
    • 使用推荐
  • RabbitMQ 高可用
    • 普通集群模式
    • 镜像集群模式
    • 保证消息队列的幂等性(消息不被重复消费)
    • 消息队列的可靠性传输
      • 生产者丢失数据
      • RabbitMQ丢失数据
      • 消费者丢失数据
    • 保证消息的顺序性
    • 消息积压问题

各种消息队列对比

特性 ActiveMQ RabbitMQ RocketMQ Kafka
单机吞吐量 万级, 吞吐量比RocketMQ和Kafka要低一个数量级 万级, 吞吐量比RocketMQ和Kafka要第一个数量级 10万级, RocketMQ也是可以支撑高吞吐的一种MQ 10万级别, 这是Kafka最大的优点, 就是吞吐量搞, 一般配合大数据类的系统来进行实时数据计算, 日志采集等场景
可用性 高, 基于主从架构实现高可用性 高, 基于主从架构实现高可用性 非常高, 分布式架构 非常高, Kafka是分布式的, 一个数据多个副本, 少数机器宕机, 不会丢失数据, 不会导致不可用
消息可靠性 有较低的概率丢失数据 经过参数优化配置, 可以做到 0 丢失 经过参数优化配置, 消息可以做到 0 丢失
时效性 ms 级 微秒级, 这是RabbitMQ的一大特点, 延迟是最低的 ms 级 延迟在 ms 级以内
功能支持 MQ 领域的功能及其完备 基于 erlang 语言开发, 所有并发能力强, 性能极其好, 延迟很低 MQ 功能较为完善, 还是分布式的, 扩展性好 功能较为简单, 主要支持简单的MQ 功能, 在大数据领域的实时计算以及日志采集被大规模使用, 是事实上的标准
优劣势总结 非常成熟, 功能强大, 在业内大量的公司以及项目中都有应用. 偶尔会出现较低概率丢失消息, 而现在社区以及国内应用都越来越少, 官方社区现在对ActiveMQ5.x 维护越来越少, 几个月才发布一个版本而且缺少主要是基于解耦和异步来用的, 较少在大规模吞吐的场景中使用 erlang 语言开发, 性能极其好, 延迟很低, 吞吐量到万级, MQ功能比较完备而且开源提供的管理界面非常棒, 用起了很好用, 社区相对比较活跃, 几乎每个月都会发布几个版本, 在国内一些互联网公司近几年用RabbitMQ也比较多, 但问题也显而易见, RabbitMQ确实吞吐量会低一些, 这是因为事先机制比较中, 而且 erlang 开发, 国内有实例做 erlang 源码基本的研究和定制不多, 基本只能依赖于开源社区的快速维护和修复bug, 而且 RabbitMQ集群动态扩展会比较麻烦. 接口简单易用, 而且在阿里大规模应用过, 日处理消息上百亿, 可以做到大规模吞吐, 性能也非常好, 分布式扩展也很方便, 社区维护还可以, 可靠性和可用性都是OK的, 还可以支撑大规模的topic数量, 支撑复杂MQ业务场景, java语音开发, 可以自己阅读源码,进行定制化开发,社区活跃度相对较为一般, 文档简单, 接口不是按照标准 JMS 官方走的, 有些系统要迁移需要修改大量代码. Kafka 的特点很明显, 就是仅仅提供较少的核心功能, 但是提供超高的吞吐量, ms 级的延迟, 极高的可用性以及可靠性, 而且分布式可以任意扩展, 同事Kafka最好是支撑较少的 topic 数量即可. 保证超高吞吐量, 唯一劣势是有可能消息重复消费, 对数据准确性会造成极其轻微的影响. 在大数据领域中以及日志采集中, 这点轻微影响可以忽略这个特性, 天然适合大数据实时计算以及日志收集

使用推荐

  • ActiveMQ 没有经历过大规模吞吐量场景验证, 社区也不是很活跃, 不推荐
  • RabbitMQ 有比较稳定的支持, 社区活跃度搞, 中小型公司推荐
  • RocketMQ 阿里出品,社区活跃度没有 RabbitMQ 搞, 需要二次开发, 推荐大型公司使用
  • Kafka 大数据领域的业内标准, 实时计算, 日志采集等

RabbitMQ 高可用

  • 单机模式
  • 普通集群模式
  • 镜像集群模式(高可用)

普通集群模式

在多台机器上启动多个RabbitMQ实例,每个机器启动一个创建queue只会放在一个RabbitMQ实例上, 但是每个实例都会同步queue的元数据, 消费的时候, 实际上如果连接通道另一个实例, 呢么就会从queue所在的实例上去拉取数据, 如果那个放queue的实例宕机了, 就会导致其他实例无法从这个实例上拉取实际, 这个方案主要是提高吞吐量, 就是让集群中多节点来服务耨个queue的读写操作

RabbitMQ高可用_第1张图片

镜像集群模式

该模式才是高可用模式, 在镜像集群模式下, 创建的queue会存在多个实例, 每个节点都会有一份万总的queue镜像, 每次写消息到queue时, 会自动把消息同步到多个实例的queue上.开启该模式就是新增一个镜像集群模式策略

好处: 任何一个机器宕机, 可以到其他节点去消费数据

坏处: 性能开销太大, 需要同步到所有集群, 不是分布式的

RabbitMQ高可用_第2张图片

保证消息队列的幂等性(消息不被重复消费)

结合业务分析

  • 比如拿个数据要写库, 先根据主键查询, 如果该数据已存在, 就不插入, 而是进行修改
  • 如果是写入Redis, 那就没问题, 因为每次set天然幂等性
  • 如果需要让生产者发送每天数据的时候, 里面加一个全局唯一 ID, 到消费这里, 先根据这个id去查询判断之前是否有过消费, 如果没有消费那就进行处理, 如果消费过就不进行处理
  • 基于数据的唯一键来保证重复数据不会重复插入多条, 有了唯一键约束, 重复数据插入会报错, 不会导致脏数据出现

消息队列的可靠性传输

RabbitMQ高可用_第3张图片
RabbitMQ高可用_第4张图片

生产者丢失数据

事务机制

使用RabbitMQ的事务功能, 在生产者发送数据之前开启RabbitMQ事务,然后发送消息, 如果消息没有发送成功被RabbitMQ接收到, 那么生产者会收到异常报错, 此时就可以回滚事务, 然后重试发送. 如果收到可以提交事务就可以提交事务. 缺点是吞吐量会下来, 太耗性能

confirm 机制

还可以开启 confirm 模式, 每次写的消息都会被分配一个唯一id, 然后写入 RabbitMQ 中, RabbitMQ 会回传一个 ack 消息, 告诉你消息OK了, 如果 RabbitMQ 没有处理这个消息, 会回调 nack 接口, 告诉你消息接收失败, 可以重试

事务机制和 confirm 机制区别

  • 事务是同步的, 提交一个事务后会阻塞在那
  • confirm 机制是异步的, 发送这个消息后就可以发送下一个消息, 然后 RabbitMQ接收后会异步回调接口通知消息已接收

一般推荐使用 confirm 机制

RabbitMQ丢失数据

开启RabbitMQ的持久化, 恢复之后会自动读取之前存储的数据, 一般不会丢失数据, 除非RabbitMQ还没完成持久化就挂了, 可能会丢失少量数据, 概率太小

设置持久化步骤

  1. 创建queue时将其设置为持久化, 保证 queue的元数据, 但是不会持久化queue里的数据
  2. 发送消息的时候将消息的 deliverMode 设置为 2 . 就是持久化消息

必须同时设置上面两个才能持久化, 还可以跟生产者那边的 confirm 机制配合, 只有消息被持久化到磁盘后才通知生产者 ack

消费者丢失数据

消费者刚拿到数据, 还没开始处理系统就挂了

可以使用 RabbitMQ 提供的 ack机制, 关闭RabbitMQ的自动ack, 在处理完后手动ack, 没手动确认ack的话, RabbitMQ会认为还没处理完, 消息是不会丢失的

保证消息的顺序性

才分多个queue, 每个queue对应一个消费者, 然后在这个消费者内用内存队列排队, 然后分给不同的worker来处理
RabbitMQ高可用_第5张图片

消息积压问题

  • 仅仅是消费者消费速度落后于生产速度, 可以扩容消费者群组
  • 积压严重
    • 修复现有消费者问题,然后停掉
    • 重新创建一个容量更大topic, 比如分区是原来的10倍
    • 编写一个临时消费者程序, 消费来源积压的队列, 不做任何耗时处理, 将消息均写入新创建的队列中
    • 将修复好的消费者部署到原来10倍的机器上消费新队列
    • 解决后恢复原有架构
  • 消息有过期失效机制, 已经丢失大量数据, 只能将丢失的数据写入程序查询出来后重新写入MQ中

你可能感兴趣的:(RabbitMQ,队列,分布式,rabbitmq)