在直播系统中选择消息队列的考量与决策

前言

面试时面试官一问到MQ你了解吗?能讲下你们项目中MQ用来干什么吗?大多数人的第一回答是:"异步消息处理,削峰填谷",今天教你们一招能瞬间让面试官打起精神的回答,下次面试时你们可以这样说:MQ就像是一个神奇的邮递员,它可以将消息快速、可靠地传递到各个系统中,它的作用就像是一个桥梁,连接了不同的系统,使得它们能够顺畅地交流和协作。 顿时格局就上来了,这时面试官的心理活动:这小子理解总结得蛮透彻的,今天我得在MQ上多盘他几下....

业务场景

MQ使用场景介绍

  1. 直播间内送礼、特效、公屏、弹幕等需要用到MQ异步处理
  2. 分布式环境下本地缓存的刷新需要用到MQ通知刷缓存
  3. 耗时长/并发高的业务需要用到MQ做削峰填谷
  4. 不同微服务中需要用到MQ做系统解耦
  5. 分布式微服务环境下需要广播、集群、延迟消费,有时甚至需要使用事务消费解决分布式事务问题

MQ选型要求

  1. 需要一个可大规模集群部署(高可用性)的MQ
  2. 需要一个吞吐量高、延迟低的MQ
  3. 需要一个支持多种消费模式的MQ
  4. 需要一个好落地、社区较完善、易扩展的MQ

业内常用MQ

1. ActiveMQ

特点:

  • 支持多种消息传输协议:ActiveMQ 支持多种消息传输协议,如 JMS、AMQP、STOMP 等。
  • 支持多种消息模型:ActiveMQ 支持多种消息模型,如点对点模型、发布订阅模型等。
  • 支持多种消息类型:ActiveMQ 支持多种消息类型,如文本消息、对象消息、字节消息等。

优点:

  • 支持多种消息传输协议、模型和类型,灵活性较高;
  • 可以方便地与 Spring 等框架进行集成。

缺点:

  • ActiveMQ 的性能相对较低,不能满足高并发、高吞吐量的消息传输需求;
  • 部署和配置相对复杂,需要投入大量的时间和精力。

使用场景:

  • 需要与其他JMS规范的系统集成;
  • 需要支持多种协议的通信;
  • 对性能要求不高的中小型系统。

使用上可能存在的坑:

  • JMS API 的使用问题:ActiveMQ 是基于 JMS API 的消息中间件,需要开发人员熟练掌握 JMS API 的使用方法。
  • 内存泄漏问题:ActiveMQ 的性能受限于内存,如果存在内存泄漏等问题,可能会导致系统崩溃。
  • 消息堆积问题:如果消费者处理消息的速度跟不上生产者的速度,可能会导致消息堆积。需要根据实际情况来调整消费者的数量和速度。

ActiveMQ适合用于分布式系统之间的消息通信、异步任务处理等应用场景。

2. RabbitMQ

特点:

  • 高度可靠性:RabbitMQ 提供了多种可靠性保证机制,如消息确认机制、持久化等。
  • 良好的性能:RabbitMQ 的性能优秀,能够支持高并发、高吞吐量的消息传输。
  • 灵活的路由:RabbitMQ 支持灵活的路由策略,能够满足不同场景下的需求。

优点:

  • 提供了多种可靠性保证机制,消息不易丢失;
  • 性能优秀,支持高并发、高吞吐量的消息传输;
  • 灵活的路由策略,满足不同场景下的需求。

缺点:

  • 部署和配置比较复杂;
  • RabbitMQ 仅支持单个节点的横向扩展,不支持集群的纵向扩展。

使用场景:

  • 对性能要求较高的大规模系统;
  • 需要支持多种协议的通信;
  • 对消息传输的稳定性和可靠性要求较高的系统。

使用上可能存在的坑:

  • 配置文件问题:在 RabbitMQ 的配置文件中,可能存在一些常见的坑点,如配置文件缺失、配置不当等。
  • 内存问题:RabbitMQ 的性能受限于内存,因此需要根据实际需求来分配内存。
  • 消息丢失问题:如果 RabbitMQ 节点宕机或者网络故障,可能会导致消息丢失。需要使用可靠的消息投递机制(如消息确认机制)来保证消息的可靠性。

RabbitMQ 适合用于任务分发、消息通知、日志处理、大数据处理、在线聊天等应用场景。

3. Kafka

特点:

  • 支持高吞吐量的消息传输;
  • 支持消息的批量处理和压缩;
  • 支持分布式部署;
  • 具有较好的性能和可靠性。

优点:

  • 性能极佳,支持高并发和大规模的消息传输;
  • 支持多种特性,如消息压缩、批量处理等;
  • 具有良好的可扩展性和可靠性。

缺点:

  • 功能较为简单,不支持复杂的消息处理场景;
  • 社区支持相对较少。

使用场景:

  • 对性能要求极高的大规模系统;
  • 对消息传输的可靠性和稳定性要求较高的系统。

使用上可能存在的坑:

  • 配置问题:Kafka 的配置非常灵活,但也容易出错。需要根据实际需求来配置 Kafka 的参数。
  • 磁盘空间问题:Kafka 存储所有的消息数据,因此需要足够的磁盘空间来存储数据。
  • 服务异常问题:Kafka 的服务可能因为各种原因异常,需要监控服务状态并及时处理。

Kafka适合用于日志处理、实时数据处理、流式处理等应用场景。

4. RocketMQ

特点:

  • 支持主从架构和Broker集群;
  • 支持消息的有序传输和有序消费;
  • 支持高可用和消息事务等特性;
  • 具有较好的性能和可靠性。

优点:

  • 高可用性,支持主从架构和Broker集群;
  • 对消息的有序传输和有序消费支持较好;
  • 支持事务消息,保证消息传输的可靠性;
  • 性能较为优秀,支持高并发和大规模的消息传输。

缺点:

  • 社区相对较小,文档资料相对较少;
  • 部署和配置相对较为复杂。

使用场景:

  • 对可用性和消息传输的可靠性要求较高的大规模系统;
  • 需要支持有序消息传输和消费的系统;
  • 对消息事务有较高要求的系统;
  • 需要支持大规模数据传输和高并发的系统。

使用上可能存在的坑:

  • 服务端配置问题:RocketMQ 的性能受限于服务端的配置,需要根据实际需求来配置服务端参数。
  • 客户端使用问题:RocketMQ 的客户端使用比较复杂,需要开发人员熟练掌握客户端的使用方法。
  • 消息消费问题:RocketMQ 的消息消费可能存在重复消费、消息丢失等问题,需要使用可靠的消息消费机制来保证消息的正确性。

RocketMQ适合用于高并发、大数据量、有序消息传输、分布式事务等应用场景。

5. Redis

不要笑,真的可以用来做MQ,你要知道并不是所有的业务都需要消息高可用的,甚至有些业务允许你丢消息,所以它也是适用于某些场景的。

特点:

  • 基于内存存储,读写速度快;
  • 支持多种数据结构,如List、Set、Hash等;
  • 支持多种消息模式,如发布/订阅、点对点等;
  • 支持消息持久化。

优点:

  • 高性能,读写速度快;
  • 可以使用多种数据结构存储数据,比传统MQ更加灵活;
  • 支持多种消息模式,可以适应不同的业务需求;
  • 可以使用AOF和RDB两种方式进行数据持久化,保证消息不丢失。

缺点:

  • 不支持消息的事务处理;
  • 不支持消息的回溯和消费确认;
  • 单机性能受限,不适用于大规模集群。

使用场景:

  • 适合对性能要求较高的业务场景,如实时性要求高的在线游戏、实时消息推送等;
  • 适合对数据结构存储需求较多的场景,如分布式缓存、统计数据聚合等;
  • 适合对消息发布/订阅需求较多的场景,如消息通知、实时广播等;
  • 适合对轻量级MQ系统的需求,如小型项目、中小企业等。

使用上可能存在的坑:

  • 持久化配置问题:Redis 支持多种持久化方式,需要根据实际需求来配置持久化方式和参数。
  • 内存问题:Redis 的性能受限于内存,需要根据实际需求来分配内存。
  • 客户端连接问题:Redis 的客户端连接可能存在超时、重试等问题,需要使用可靠的连接机制来保证客户端的稳定性。

Redis做MQ系统,可以为一些小型或中小型的应用提供简单、高性能、灵活的消息传输服务,但是对于大规模集群或高并发的业务场景来说,显然不适用。

选型分析

RabbitMQ

企业级应用,大规模数据处理,传输可靠性要求高的场景

微软、VMware、华为

Kafka

流式处理,大数据量场景,高吞吐低延迟的实时消息处理

Netflix、LinkedIn、Uber

ActiveMQ

适用于较小规模的应用,消息传输可靠性要求一般的场景

Apache、Adobe、Red Hat

RocketMQ

高并发、高吞吐量,低延迟的互联网应用场景

阿里巴巴、美团、京东

Redis

极低

缓存和计算场景,数据量较小,对延迟要求极高的实时应用

Twitter、GitHub、滴滴

业务场景可行性分析

  1. RabbitMQ:RabbitMQ适用于传输可靠性要求较高的企业级应用,但在高并发、高吞吐量和低延迟的社交直播场景中可能存在性能瓶颈。
  2. Kafka:Kafka具有高吞吐量和低延迟的特点,适用于处理海量数据和实时流式处理的场景,但在社交直播场景中可能存在实时性不足的问题。
  3. ActiveMQ:ActiveMQ适用于传输一般性质的消息,但在高并发、高吞吐量和低延迟的社交直播场景中可能存在性能瓶颈。
  4. RocketMQ:RocketMQ适用于高并发、高吞吐量和低延迟的互联网应用场景,支持多语言客户端和分布式事务,具有高可用性和性能表现。在社交直播场景中,RocketMQ可以满足高并发、高吞吐量和低延迟的消息交互和推送需求。
  5. Redis:Redis主要用于缓存和计算场景,对延迟要求极高的实时应用,但在社交直播场景中可能存在消息不可靠、数据量过大的问题。

最终方案确认

综合考虑以上因素,我们选择RocketMQ作为社交直播应用中的消息队列。RocketMQ具有高并发、高吞吐量和低延迟的特点,可以满足实时消息交互和推送的需求。此外,RocketMQ还支持分布式事务和多语言客户端,可以保证数据传输的可靠性和灵活性

为什么是RocketMQ而不是Kafka?

再次回答一下来自标题的灵魂发问,我知道其实很多大厂都在用着Kafka,它在高吞吐量、低延迟、可扩展性、活跃的开源社区等方面表现出色,这些因素都是其受大厂欢迎的主要原因之一,也是很多大型企业选择使用Kafka的原因。

为什么选择RocketMQ,不是因为它比Kafka多优秀,主要有以下几个原因:

  1. 实时性要求更高:社交直播应用需要实时的消息交互和推送,因此消息队列需要具备低延迟的特点。虽然Kafka也具有低延迟的特点,但是相较于RocketMQ,其设计和实现更偏向于数据流处理,而不是面向实时消息的传输,可能不太适合社交直播场景的实时性要求。
  2. 开发效率更高:RocketMQ具有简单易用的API和广泛的客户端支持,可以在社交直播场景中提高开发效率。而Kafka的客户端相对较少,需要使用者自行编写定制化代码,这可能会增加开发难度和复杂度。
  3. 更好的容错性和可靠性:在社交直播场景中,消息丢失或传输失败可能会对用户体验产生负面影响。RocketMQ在容错性和可靠性方面设计得更为严格和稳定,具有更好的消息可靠性和数据一致性。Kafka在这方面的表现也非常优秀,但相比之下,RocketMQ在此方面的表现可能更为稳定。

所以总之一句话就是,RocketMQ会被我们优先选择,而Kafka可能不太适合在社交直播场景中使用。

RocketMQ在云原生上的表现

  1. 容器化支持:RocketMQ已经容器化,可以方便地在云原生环境中部署和管理,如Kubernetes。
  2. 弹性伸缩:RocketMQ支持按需伸缩,可以根据业务负载自动伸缩,提高了消息系统的可用性和可扩展性。
  3. 高可用性:RocketMQ提供了主从复制和多活部署等机制,能够保证消息系统的高可用性,避免了单点故障。
  4. 可观测性:RocketMQ提供了完善的监控和告警系统,可以方便地观测消息系统的运行状态,及时发现并解决问题。
  5. 开放性:RocketMQ是一款开源的消息中间件,支持多种编程语言和平台,可以方便地集成到各种分布式系统中。

RocketMQ在云原生时代的支持与优势非常明显,可以帮助用户更好地构建可靠、高效、高可用的分布式消息系统。

#从0到1千万级直播项目#
从0-1开发千万级直播项目 文章被收录于专栏

文章内容源自本人所在互联网社交企业实战项目,分享、记录从0-1做一个千万级直播项目,内容包括高并发场景下技术选型、架构设计、业务解决方案等。

全部评论

相关推荐

面试官人很好,态度和蔼可亲,没答出来时也会引导你去思考。由于是晚上面的,导致我白天一天都有点紧张,面的时候状态也不是很好,正常可能面试官提问完应该思考几秒再答,而我就像抢答一样一口气把所有会的都说出来,这样就导致逻辑比较混乱,东一句西一句的。首先是自我介绍,先把会的技术大致讲一下,由于我八股背的多所以着重讲了一下,Java,go,jvm,MySQL,Redis,计网,操作系统这些,然后一小部分闲聊,然后先问了一下项目,面试官问我这个项目是否落实之类的,直接坦言说是写的练手的,包括之前也写过IM通讯,外卖之类的。然后面试官就把提问的重点放在了八股上。先问了Java:类加载器(答:3种+自定义类加载器、tomcat、原因+双亲委派+好处)JVM参数(答:xmx,xms,newsize这些,问我是如何设定的,我回答是把内存分一半给堆,再把堆分一半给新生代,这方面确实不太了解)然后问了一下并发相关的:线程池(答:线程池的7个参数(忘了线程工厂和阻塞时间了),3个重要参数,还有线程如何启用,为什么要设计最大线程数之类的,提到Java栈默认分配1MB运行时不可以更改)AQS(答:先讲clh是自旋锁+list,然后是AQS在这个基础上做的两个优化,然后举了一下reentrantlock根据state如何获取资源)CAS(答:使用三个字段,aba问题,然后将通常搭配自旋锁实现,面试官问通常会自旋多少次,这个不太了解,答的100,然后问100次大概多少秒,回答微秒级,然后面试官讲了一下怎么做资源可能没用完,意识到可能还需要进行阻塞操作)然后考虑一下Linux命令(top,ps,如何使用管道符过滤线程和使用Linux启动线程没答出来)然后问Redis:持久化机制(答:三种aof,rdb,混合,aof的三个参数刷盘策略,rdb以快照保存,使用bgsave会使用子线程来保存不会阻塞,而aof虽然会阻塞但是只在写完数据后追加一条命令,不会太影响,然后是他俩的优缺点,还有混合是怎么保存数据的)集群模式(答:三种,主从复制到缺点再到哨兵机制,正常使用三个哨兵互相监督,主节点挂了投票选主哨兵然后选主节点,然后额外讲一下脑裂的问题,主节点进行数据更新然后把命令写入aof来同步从节点,最后cluster集群,如何实现,使用16383个哈希槽(艹答成16384了),先根据哈希码取余,再根据节点数取余决定放在哪个节点上,然后问了一下我会怎么选集群模式,首先是cluster的问题,会让管道操作之类的失效,然后哨兵会导致整个集群结构变得复杂,使用小项目可能会考虑哨兵,大的考虑cluster,然后考了一下cluster如果一个节点挂了怎么办,根据节点数重新取余然后数据转移,面试官说这么转移比较慢,有没有别的办法,我隐约记得使用一个类似环形数组的方式,想不起来了)然后考了一下MySQL的b+树(这方面的知识点太多了,导致我什么都想讲逻辑就比较乱,讲了一下聚簇索引,树的叶子节点对应着一张页16KB,MySQL有一个区的概念,把这些页放在同一个区中,这样叶子节点的双向链表遍历时速度更快,然后b+树的扇出比较大(非常二,说成扇度之类的,面试官以为说的是扇区)这样层数就比较小,一行1kb数据的话3层可以放心2000w数据)其他的暂时想不起来了算法是lru,面试官问要不要提示,我说写个,然后写了10分钟左右,说大概写好了,但是面试官指出了2个小错误,第一个马上就改回来了,第二个一直没看出来(大脑这时候已经停止工作了)反问:问学习建议,说根据实际的项目进行深入,考虑应该怎么做,还问了一下组里面是做Java的吗?面试官说他是做go的,组里什么语言都有,语言影响不大,连忙补充了一句我对go的底层有深入源码的学习)结束。总体感觉答得不太好,没有太体现出深度,细节也不够全面。
下一个更好呗:佬,我投完云智一直没消息,多久约的一面啊
查看14道真题和解析
点赞 评论 收藏
分享
评论
4
19
分享

创作者周榜

更多
牛客网
牛客企业服务