特性 | 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 数量即可. 保证超高吞吐量, 唯一劣势是有可能消息重复消费, 对数据准确性会造成极其轻微的影响. 在大数据领域中以及日志采集中, 这点轻微影响可以忽略这个特性, 天然适合大数据实时计算以及日志收集 |
在多台机器上启动多个RabbitMQ实例,每个机器启动一个创建queue只会放在一个RabbitMQ实例上, 但是每个实例都会同步queue的元数据, 消费的时候, 实际上如果连接通道另一个实例, 呢么就会从queue所在的实例上去拉取数据, 如果那个放queue的实例宕机了, 就会导致其他实例无法从这个实例上拉取实际, 这个方案主要是提高吞吐量, 就是让集群中多节点来服务耨个queue的读写操作
该模式才是高可用模式, 在镜像集群模式下, 创建的queue会存在多个实例, 每个节点都会有一份万总的queue镜像, 每次写消息到queue时, 会自动把消息同步到多个实例的queue上.开启该模式就是新增一个镜像集群模式策略
好处: 任何一个机器宕机, 可以到其他节点去消费数据
坏处: 性能开销太大, 需要同步到所有集群, 不是分布式的
结合业务分析
事务机制
使用RabbitMQ的事务功能, 在生产者发送数据之前开启RabbitMQ事务,然后发送消息, 如果消息没有发送成功被RabbitMQ接收到, 那么生产者会收到异常报错, 此时就可以回滚事务, 然后重试发送. 如果收到可以提交事务就可以提交事务. 缺点是吞吐量会下来, 太耗性能
confirm 机制
还可以开启 confirm 模式, 每次写的消息都会被分配一个唯一id, 然后写入 RabbitMQ 中, RabbitMQ 会回传一个 ack 消息, 告诉你消息OK了, 如果 RabbitMQ 没有处理这个消息, 会回调 nack 接口, 告诉你消息接收失败, 可以重试
事务机制和 confirm 机制区别
一般推荐使用 confirm 机制
开启RabbitMQ的持久化, 恢复之后会自动读取之前存储的数据, 一般不会丢失数据, 除非RabbitMQ还没完成持久化就挂了, 可能会丢失少量数据, 概率太小
设置持久化步骤
必须同时设置上面两个才能持久化, 还可以跟生产者那边的 confirm 机制配合, 只有消息被持久化到磁盘后才通知生产者 ack
消费者刚拿到数据, 还没开始处理系统就挂了
可以使用 RabbitMQ 提供的 ack机制, 关闭RabbitMQ的自动ack, 在处理完后手动ack, 没手动确认ack的话, RabbitMQ会认为还没处理完, 消息是不会丢失的
才分多个queue, 每个queue对应一个消费者, 然后在这个消费者内用内存队列排队, 然后分给不同的worker来处理