写点什么

腾讯课堂百万师生同时在线,如何实现消息的稳定互动?

2021 年 1 月 15 日

腾讯课堂百万师生同时在线,如何实现消息的稳定互动?

疫情期间,为了保障国内学子的正常学习进度,腾讯课堂积极响应国家“停工不停学”的号召,紧急上线疫情期间专用的“老师极速版”,使广大师生足不出户,即可快速便捷的完成线上开课。面对线上课堂百万量级的互动消息,如何保证消息的实时性和准确性无疑是一个技术挑战。那么如何解决问题呢?接下来,就和小编一起来看看腾讯云中间件 CKafka 如何为腾讯课堂百万级消息提供技术支撑。


引言


两年前,腾讯在线教育部就在探索如何实现架构转型。在梳理过腾讯课堂初始技术架构的痛点后,规划出架构演进的三个重点方向:微服务、中间件、DevOps。尤其在消息中间件的选取上,从自研 Hippo 消息队列切换到云 CKafka。这主要归于以下几点原因:


  • 实现技术栈的统一,降低组件适配成本。

  • 使用符合开源标准的组件,便于系统切换优秀的开源组件。

  • CKafka具备高性能、高可用性和高可靠性的特点:免除复杂的参数配置,提供专业的性能调优;磁盘高可靠,即使服务器坏盘50%也不影响业务;多副本备份,更有多可用区容灾方案可选,零感知服务迁移。

  • CKafka提供安全的数据保障:提供鉴权与授权机制、主子账号等功能,为企业数据做好安全防护。


在刚刚过去的 2019 年,腾讯在线教育部已全面实现了业务上云,不仅提升了团队研发效率,还实现了快速交付。同时,CKafka 在消息流处理上的高性能特点得以实践验证。


而现在,疫情当前,面对全国千万师生同时在线的线上课堂,互动消息猛增至百万级别,无疑对在线教育平台的稳定性提出更高要求。


为了保证线上课堂广大师生的稳定互动,CKafka 作为腾讯课堂的底层消息支撑,在消息的实时性和可靠性上提供了更优化的技术方案。



CKafka 在腾讯课堂的实践


Ckafka 在腾讯课堂系统架构中的应用是非常典型的场景,即消息总线和业务解耦。使用了 GB 带宽、TB 存储规格的实例。


我们先来看一下 CKafka 作为消息总线在腾讯课堂的架构中所处的位置,如下图:



从架构图可知,CKafka 处于消息管道的中心位置。同时接收多个消息源数据,等待下游组件的订阅消费。


并利用其自身高分布式、高吞吐、高可靠的特性,实现流量削峰和业务解耦。腾讯课堂中的聊天消息、签到、举手、献花、答题卡等功能都使用了该能力。


在线课堂的业务场景不允许出现如消息延迟、数据丢失等情况,否则就会立刻被在线课堂的师生们感知业务的不稳定,造成不良的用户体验。


我们来假设一个场景:老师在课堂发布一个问题,学生们举手回答问题,如果老师发出的消息出现延时或丢失的情况,学生们就不能收到消息,无法及时给老师反馈问题答案,线上课堂的互动效果就会很差,严重影响课堂教学质量。


如何避免上述问题呢?我们从 CKafka 保障消息的实时性和可靠性两方面进行阐述。


消息的实时性


Apache Kafka 架构上设计的底层数据读写和存储是以分区为最小单位进行的。首先来看一下 Kafka Topic 的生产消费模型。



如上图所示,生产者将数据写入到分布在集群内不同节点的不同分区上,一个或多个消费者从多台 Borker 的分区上消费订阅数据。


从这个模型可知,如果数据的读写都集中在单个分区上,则 Topic 的的所有压力都会集中在该分区上,从而落到单台 Broker 上面。


假设单台机器能承受的流量是 300MB,则此时以腾讯教育的 GB/s 的流量规模,则会出现消息处理过慢,会导致消息延时。


那怎么办呢?此时就应该提升分区的数量,提高数据处理的并行度,从而将整个 topic 的压力均分到多台机器上。


这时就会有一个疑问,Topic 需要多少分区合适呢?是不是越多的分区越好呢?


(1)影响分区数量的因素


从生产者的角度来看,数据向不同的分区写入是完全并行的;从消费者的角度来看,并发数完全取决于分区的数量(如果 consumer 数量大于 分区 数量,则必有 consumer 闲置)。


因此选取合适的分区对于发挥 CKafka 实例的性能十分重要。


Topic 的分区数量是由多种因素决定的,一般可以根据以下几个因素综合考虑:


  • 生产者的峰值带宽

假设单机单 partiton 的生产消费吞吐各自最高为 300,峰值生产带宽是 900MB,则单纯生产至少需要 3 个 Partiton。


  • 消费者的峰值带宽

有人可能会觉得消费的峰值带宽应该等于生产的峰值带宽。这样是不对的。生产者只会生产一份数据,但是可以有 N 个消费者消费同一份数据,则此时消费带宽=N*生产带宽。

另外如果是离线计算,可能会在某一时刻,消费历史所有数据,此时消费带宽可能会远远高于生产带宽。此时如果 Topic 只设计 3 个分区就有问题了。假设消费峰值带宽是生产带宽的 2 倍。则此时至少需要 6 个分区。


  • 消费者的处理能力

假设创建了 6 个分区。此时 6 个分区最多只会有 6 个消费者,每个消费者最多每秒可以从 Kafka Server 拉到 300MB 的数据。


但是每个消费者因为还需处理业务逻辑的关系,只能消费 100MB 的数据,这样就会容易导致出现消费堆积的情况。


为了增大消费能力,则需要多加入消费者。因为 Kafka 的 consumer group 机制里同一个消费组里同一个分区只能被一个消费者消费。所以,就应该增大分区的数量。


为满足如上需求,此时至少需要 18 个分区,18 个消费者,才能满足消费需求。


在上面的 Case 中,分区数的设计也需要存在一定的冗余,因为很多情况下,性能是无法达到最优的。

所以,分区数量需要综合考虑多个因素,可以适当的多一点分区数量,以提高实例的性能。但也不能太大,太大也会导致一系列的其他问题。


(2)选取合适的分区数量


考虑到上面提到的实际因素,是否有一个相对简单的判断方法来设计分区数量呢?


在理想情况下,可以通过如下公式来判断分区的数目:


Num = max( T/PT , T/CT ) = T / min( PT , CT )


其中,Num 代表分区数量,T 代表目标吞吐量,PT 代表生产者写入单个 分区 的最大吞吐,CT 代表消费者从单个分区消费的最大吞吐。则分区数量应该等于 T/PT 和 T/CT 中的较大值。


在实际情况中,生产者写入分区的最大吞吐 PT 的影响因素和批处理的规模、压缩算法、确认机制、副本数等有关。


消费者从单个分区消费的最大吞吐 CT 的影响因素和业务逻辑有关,需要在不同场景下实测得出。


通常建议分区的数量一定要大于等于消费者的数量来实现最大并发。如果消费者数量为 5,则分区的数目也应该 ≥ 5 的。


但需要注意的是:过多的分区会导致生产吞吐的降低和选举耗时的增加,因此也不建议过多分区。


提供如下信息供参考:


  • 单个分区是可以实现消息的顺序写入的。

  • 单个分区只能被同消费者组的单个消费者进程消费。

  • 单个消费者进程可同时消费多个分区,即分区限制了消费端的并发能力。

  • 分区越多,当Leader节点失效后,其他分区重新进行Leader选举的耗时就会越长。

  • 分区的数量是可以动态增加的,只能增加不能减少。但增加会出现消息 rebalance 的情况。

在上述方法的基础上,我们还综合考虑了腾讯课堂的生产消费峰值带宽、消费的行为特征和单个消费者的消费能力等因素,为其设计了合理的分区数量,以满足其对消息实时性的要求。


消息的可靠性


消息的可靠性从不同的角度看是不一样的。


从 Apache Kafka 自身角度看来,消息的可靠性是消息的可靠存储。从业务的角度来看,消息的可靠性是指消息传输、存储、消费的可靠性。


从服务提供商来看,我们希望消息的可靠性是站在客户这一边的,即可靠的传输,存储,消费。


CKafka 在做好可靠性存储的基础上,还从配置调优、异常告警等方面尽量做到消息的可靠传输和消费。


(1)关于副本


在介绍下面的方案前,我们先聊聊一下副本。为什么要有副本的存在呢?


在分布式的场景下,数据损坏和机械故障是被认为常见事件。


数据副本是指在不同节点上持久化同一份数据,当某一个节点上存储的数据丢失时,可以从副本上读取该数据,这是解决分布式系统数据丢失问题最为有效的方法。


那么我们来思考下:有多少个副本的数据才是安全的?


理论上 2 个副本就可以大概率范围的保证数据安全,但是当两个副本都损坏时,数据也会丢失,此时就需要更多的副本,或者需要副本跨可用区、跨地域分布。


当然更多的副本就意味着要存储更多的数据,需要更高的成本投入。所以用户需要在冗余和安全之间权衡出一种平衡。这也是腾讯云上创建 topic 需要用户指定副本数量的原因,如下图:



(2)服务端的可靠性


假设 TopicA 有 3 个分区,每个分区有三个副本。来看一下如下的 Topic 分区分布示意图。



如图所示,三个分区和三个副本均匀的分布在三个 Broker 中,每台 Broker 分布了一个分区的 Leader 分区。


从上一节关于副本的描述可知,除非所有的 Broker 在同一时间挂掉,否则即使同时挂掉 2 台 Borker,服务也可以正常运行。


而在我们当前的运营架构中,三台 broker 同时挂掉的概率微乎其微,当然如果真的出现这种情况,那就是整个机房挂掉了。


为了避免整个机房挂掉的情况,腾讯云 Ckafka 也可以配置跨机房容灾和跨可用区容灾,来保证数据的可靠性。关于跨可用区容灾相关的技术点可以点击链接查阅:《蘑菇街千亿级消息Kafka上云实践》


我们可以通过参数配置来尽可能的保证可靠性传输和消费,用告警来做兜底策略,让研发感知介入处理。下面来看一下生产和消费端的参数调优。


(3)客户端参数调优


生产的可靠传输,主要来看一下如下三个配置: ack、retries。


  • ack


Kafka producer 的 ack 有 3 种机制,分别说明如下:


-1:Broker 在 leader 收到数据并同步给所有 ISR 中的 follower 后,才应答给 Producer 继续发送下一条(批)消息。这种配置提供了最高的数据可靠性,只要有一个已同步的副本存活就不会有消息丢失。

0:生产者不等待来自 broker 同步完成的确认,继续发送下一条(批)消息。这种配置生产性能最高,但数据可靠性最低(当服务器故障时可能会有数据丢失) 。

1:生产者在 leader 已成功收到的数据并得到确认后再发送下一条(批)消息。这种配置是在生产吞吐和数据可靠性之间的权衡(如果 leader 已死但是尚未复制,则消息可能丢失)

用户不显式配置时,默认值为 1。如果是需要可靠性要求高的,建议设置为-1。设置为-1 会影响吞吐的性能。


  • retries


请求发生错误时重试次数,建议将该值设置为大于 0,失败重试最大程度保证消息不丢失。


消费的稳定,看一下以下配置,主要避免重复消费和频繁的消费组 Rebalance:


  • auto.offset.reset


表示当 Broker 端没有 offset(如第一次消费或 offset 超过 7 天过期)时如何初始化 offset。earliest:表示自动重置到 分区 的最小 offset


latest:默认为 latest,表示自动重置到分区的最大 offset

none:不自动进行 offset 重置,抛出 OffsetOutOfRangeException 异常


默认值为 latest。当设置为 earliest 的时候,需要注意的是:当 offset 失效后,就会从现存的最早的数据开始消费的情况,可能会出现数据重复消费的情况。


  • session.timeout.ms


使用 Kafka 消费分组机制时,消费者超时的时间。当 Broker 在该时间内没有收到消费者的心跳时,就会认为该消费者发生故障,Broker 发起重新 Rebalance 过程。


目前该值的在 Broker 的配置必须在 group.min.session.timeout.ms=6000 和 group.max.session.timeout.ms=300000 之间。


  • heartbeat.interval.ms


使用 Kafka 消费分组机制时,消费者发送心跳的间隔。这个值必须小于 session.timeout.ms,一般小于它的三分之一。


  • max.poll.interval.ms


使用 Kafka 消费分组机制时,再次调用 poll 允许的最大间隔。如果在该时间内没有再次调用 poll,则认为该消费者已经失败,Broker 会重新发起 Rebalance 把分配给它的分区 分配给其他消费者。


参数调优只能最大程度保证服务的可用,并不能保证服务的百分百可用。


客户端需要具有捕获生产,消费等行为异常的行为。当出现异常时,能够告警,以便人工处理。这样才能最大的保证业务的高可用。


CKafka 的优势


CKafka 除了作为消息管道帮助业务实现数据解耦、流量削峰外,还可以在其他场景有所作为。

1. 日志分析系统


CKafka 结合大数据套件 EMR,可构建完整的日志分析系统。


首先通过部署在客户端的 agent 进行日志采集,并将数据聚合到消息队列 CKafka,之后通过后端的大数据套件如 Spark 等进行数据的多次计算消费,并且对原始日志进行清理,落盘存储或进行图形化展示。



2. 流数据处理平台


CKafka 结合流计算 SCS , 可用于实时/离线数据处理及异常检测,满足不同场景需要:


  • 对实时数据进行分析和展示,并做异常检测,快速定位系统问题。

  • 消费历史数据进行落盘存储和离线分析,对数据进行二次加工,生成趋势报表等。



结语


腾讯云 CKafka 作为高性能、高吞吐量的消息中间件,为千万师生有序稳定的线上课堂提供了性能支撑,有效的解决了数据的实时性和可靠性问题。


特别是在业务故障时,可实现快速扩缩容,并以其全面的容错机制和故障处理机制为用户提供解决方案。


在 2020 年突如其来的疫情期间,CKafka 将与腾讯课堂一起努力,为莘莘学子们百万级的课堂互动消息做好技术支撑,为构建良好的线上课堂体验贡献一份力量


头图:Unsplash

作者:许文强

原文:https://mp.weixin.qq.com/s/wjjA_5o4G9vUTsH5tHxvlA

原文:腾讯课堂百万师生同时在线,如何实现消息的稳定互动?

来源:腾讯云中间件 - 微信公众号 [ID:gh_6ea1bc2dd5fd]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021 年 1 月 15 日 23:141

评论

发布
暂无评论
发现更多内容

模块分解总结

Mars

用领域驱动设计驱动系统的重构

积极&丧

架构师训练营第十周笔记

李日盛

学习 微服务 DDD

Week10总结

lggl

总结 作业

是的,我又换工作了

Rayjun

工作

MGR集群相关简介

Simon

MySQL 七日更

AOP的姿势之 简化 MemoryCache 使用方式

八苦-瞿昙

aop

从场景出发,日志聚类还可以这么玩

信仰圣光吧丶

AIOPS 日志聚类 日志治理

避坑指南,Elasticsearch 分页查询的两个问题,你一定要知道

AlwaysBeta

elasticsearch python 爬虫

Week10作业

lggl

作业

架构相关5

FreeOcean

13张图彻底搞懂分布式系统服务注册与发现原理

爱笑的架构师

微服务 微服务发现 服务注册与发现 七日更

炎币交易所APP系统开发|炎币交易所软件开发

开發I852946OIIO

系统开发

讨论话题 进程通信方式和锁关系

王传义

高并发

XRP瑞波币软件系统开发|XRP瑞波币APP开发

开發I852946OIIO

系统开发

最近一些让我颇有感触的话

Bruce Talk

随笔

架构师训练营第五周作业

zamkai

架构师训练营 大作业(二)

netspecial

极客大学架构师训练营

LeetCode题解:42. 接雨水,栈,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

Hadoop编程实战:HDFS API编程

罗小龙

Java hdfs 编程 大数据技术 实践

关于微服务架构

落朽

JDK、JRE、JVM,是什么关系?

小傅哥

jdk JVM 小傅哥 七日更 jre

微服务过载保护原理与实战

Kevin Wan

go 微服务 go-zero

安全架构:加密与解密

积极&丧

软件组件设计原则

积极&丧

架构师训练营 大作业(一)

netspecial

极客大学架构师训练营

Java并发底层知识,锁获取超时机制知多少?

码农架构

Java java 并发

重磅!四部门联合约谈蚂蚁集团!刚刚,约谈的主要内容曝光……

CECBC区块链专委会

金融

dubbo服务框架图&时序图

Mars

架构2期 - 第十周作业(1)

浮生一梦

极客大学架构师训练营 第十周 2组

架构师训练营第十周作业

李日盛

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

腾讯课堂百万师生同时在线,如何实现消息的稳定互动?-InfoQ