CKafka如何助力腾讯课堂实现百万消息稳定互动(上))

2020 年 3 月 01 日

CKafka如何助力腾讯课堂实现百万消息稳定互动(上))

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


两年前,腾讯在线教育部就在探索如何实现架构转型。在梳理过腾讯课堂初始技术架构的痛点后,规划出架构演进的三个重点方向:微服务、中间件、DevOps。


尤其在消息中间件的选取上,从自研 Hippo 消息队列切换到云 CKafka。这主要归于以下几点原因:


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

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

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

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


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


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


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



腾讯课堂在线课程页面


CKafka 在腾讯课堂的实践


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


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



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


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


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


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


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


1. 消息的实时性


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 的情况。


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


2. 消息的可靠性


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


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


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


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


(1)关于副本


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


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


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


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


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


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



(2)服务端的可靠性


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



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


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


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


为了避免整个机房挂掉的情况,腾讯云 Ckafka 也可以配置跨机房容灾和跨可用区容灾,来保证数据的可靠性。


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


(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 把分配给它的分区 分配给其他消费者。

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

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


本文转载自云加社区公众号。


原文链接:https://mp.weixin.qq.com/s/nmDUiyTMwI3ntNNHgAaJOw


2020 年 3 月 01 日 22:18200

评论

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

USDT支付系统开发技术方案,数字货币承兑商支付

13530558032

2020年7月云主机性能评测报告

BonreeAPM

云计算 测试 公有云 评测 排行榜

LeetCode题解:622. 设计循环队列,使用数组,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

Spring Cloud 微服务实践(0) - 开篇闲话

xiaoboey

微服务 Spring Cloud Spring Boot Spring Framework

如何进步神速

Sean

学习 个人成长

111

不在调上

为了写一份MyBatis学习笔记,腾讯T4大牛竟然每天熬夜到凌晨三点

Java成神之路

Java 编程 程序员 面试 mybatis源码

活着

GongTeng95

2020年8月北京BGP机房网络质量评测报告

BonreeAPM

测试 机房 评测 排行榜 IDC

不想搞Java了,4年经验去面试10分钟结束,现在Java面试为何这么难

Java架构师迁哥

UML练习1-食堂就餐卡系统设计

博古通今小虾米

UML

Spring Cloud 微服务实践(2) - Gateway重试机制

xiaoboey

maven Spring Cloud Gateway modules 重试

Java 基础语法

InfoQ_34a83d636158

数字货币交易所源码开发,区块链交易系统搭建服务商

13530558032

数字货币量化交易,量化对冲搬砖系统开发

13530558032

python——自定义序列类

菜鸟小sailor 🐕

CentOS 7 安装 Python 3.7

wong

Python

一次压缩引发堆外内存过高的教训

AI乔治

Java kafka JVM

大数据下单集群如何做到2万+规模?

华为云开发者社区

大数据 集群

危与机并存 保险业如何走好线上线下业务并举转型之路?

BonreeAPM

运维 监控 保险 AIOPS 系统

高速路二维码报警定位系统开发,二维码报警定位功能

13530558032

在线游戏,如何把握住1个亿以上的DAU?

BonreeAPM

运维 监控 AIOPS 系统 用户体验

Spring Cloud 微服务实践(1) - 用Initializr初始化

xiaoboey

Spring Cloud Eureka Gateway Hoxton

血的教训!千万别在生产使用这些 redis 指令

云流

redis 学习 编程 程序员

架构师训练营结业作业

superman

实践案例丨云连接CC实现跨区域多VPC与线下IDC Server互联

华为云开发者社区

云服务 IDC

最新:央行副行长详解数字人民币,信息量巨大!

CECBC区块链专委会

人民币 数字人民币

裳雨

GongTeng95

写作 写作平台

一次旅途

GongTeng95

算法大赛评委亲授通关秘籍,报名倒计时!

易观大数据

直播倒计时|30分钟带你解锁“技术写作”新技能

小红豆

技术 写作 直播 技术创作 RTC征文大赛

CKafka如何助力腾讯课堂实现百万消息稳定互动(上))-InfoQ