写点什么

百万用户同时在线的高并发直播弹幕系统是如何实现的?

  • 2020-02-24
  • 本文字数:3521 字

    阅读完需:约 12 分钟

百万用户同时在线的高并发直播弹幕系统是如何实现的?


导读:直播弹幕是直播系统的核心功能之一。如何迅速作出一个有很好扩展性的弹幕系统?如何应对业务迅速发展?相信很多工程师/架构师都有自己的想法。本文作者经历了直播弹幕从无到有,从小到大的过程,是对构建弹幕系统的经验总结。

直播弹幕指直播间的用户,礼物,评论,点赞等消息,是直播间交互的重要手段。


美拍直播弹幕系统从 2015 年 11 月到现在,经过了三个阶段的演进,目前能支撑百万用户同时在线。


本文比较好地诠释了根据项目的发展阶段,直播弹幕系统进行平衡演进的过程。这三个阶段分别是快速上线,高可用保障体系建设,长连接演进。

一、快速上线

消息模型

美拍直播弹幕系统在设计初期的核心要求是:快速上线,并能支撑百万用户同时在线。


基于这两点,我们的策略是前中期使用 HTTP 轮询方案,中后期替换为长连接方案。


因此在业务团队进行 HTTP 方案研发的同时,基础研发团队也紧锣密鼓地开发长连接系统。


直播间消息,相对于 IM 的场景,有如下几个特点:


  • 消息要求及时,过时的消息对于用户来说不重要;

  • 松散的群聊,用户随时进群,随时退群;

  • 用户进群后,离线期间(接听电话)的消息不需要重发。


对于用户来说,在直播间有三个典型的操作:


  • 进入直播间,拉取正在观看直播的用户列表;

  • 接收直播间持续发布的弹幕消息;

  • 自己发消息。


我们把礼物,评论,用户的数据都当做消息来看待。


经过考虑选择了 Redis 的 sortedset 存储消息,消息模型如下:


  • 用户发消息,通过 Zadd,其中 score 消息的相对时间;

  • 接收直播间的消息,通过 ZrangeByScore 操作,两秒一次轮询;

  • 进入直播间,获取用户的列表,通过 Zrange 操作来完成。


因此总的流程是:


  • 写消息流程是: 前端机 -> Kafka -> 处理机 -> Redis;

  • 读消息流程是: 前端 -> Redis。


不过这里有一个隐藏的并发问题:用户可能丢消息。



如上图所示,某个用户从第 6 号评论开始拉取,同时有两个用户在发表评论,分别是 10,11 号评论。


如果 11 号评论先写入,用户刚好把 6,7,8,9,11 号拉走,用户下次再拉取消息,就从 12 号开始拉取,结果是:用户没有看到 10 号消息。


为了解决这个问题,我们加上了两个机制:


  • 在前端机,同一个直播间的同一种消息类型,写入 Kafka 的同一个 partition;

  • 在处理机,同一个直播间的同一种消息类型,通过 synchronized 保证写入 Redis 的串行。


关于消息丢失的问题,总体原则: 消息按照消息号从小到大顺序写入,否则可能会丢消息。


写入消息的流程是:


1.发号器发号


2.写入 redis


如果有两个消息 A 和 B 同时做这个事情,我们期望的是:消息 A 得到 10 号,消息 A 写入 redis,消息 B 得到 11 号,消息 B 写入 redis。或者消息 B 得到 10 号,消息 B 写入 redis,消息 A 得到 11 号,消息 A 写入 redis。


但是如果出现:消息 A 得到 10 号,消息 B 得到 11 号,消息 B 写入 redis,消息 A 写入 redis。这样问题就来了,某个用户在消息 A 写入前把 11 号消息读走,那么他将再也不会读取到 10 号消息。


关于降级后,又回到可能丢消息的情况,这个其实是会的,但在延迟和丢消息之间,我们选择可能丢消息。相比一直允许可能丢消息,我们这种方式更好接受一些。


消息模型及并发问题解决后,开发就比较顺畅,系统很快就实现上线,达到了预先设定的目标。


上线后暴露问题的解决方案


上线后,随着消息量的逐渐增加,系统陆续暴露出三个比较严重的问题,我们一一进行了解决。


问题一:消息串行写入 Redis,如果某个直播间消息量很大,那么消息会堆积在 Kafka 中,消息延迟较大。


解决办法:


  • 消息写入流程:前端机-> Kafka -> 处理机 -> Redis;

  • 前端机:如果延迟小,则只写入一个 Kafka 的 partion;如果延迟大,则这个直播的这种消息类型写入 Kafka 的多个 partion;

  • 处理机:如果延迟小,加锁串行写入 Redis;如果延迟大,则取消锁。


因此有四种组合,四个档位,分别是:


1.一个 partion,加锁串行写入 Redis, 最大并发度:1;


2.多个 partition,加锁串行写入 Redis,最大并发度:Kafka partion 的个数;


3.一个 partion,不加锁并行写入 Redis,最大并发度:处理机的线程池个数;


4.多个 partion,不加锁并行写入 Redis,最大并发度: Kafka partition 个数处理机线程池的个数。


  • 延迟程度判断:前端机写入消息时,打上消息的统一时间戳,处理机拿到后,延迟时间 = 现在时间 - 时间戳;

  • 档位选择:自动选择档位,粒度:某个直播间的某个消息类型。


问题二:用户轮询最新消息,需要进行 Redis 的 ZrangByScore 操作,redis slave 的性能瓶颈较大。


解决办法:


  • 本地缓存,前端机每隔 1 秒左右拉取一次直播间的消息,用户到前端机轮询数据时,从本地缓存读取数据;

  • 消息的返回条数根据直播间的大小自动调整,小直播间返回允许时间跨度大一些的消息,大直播间则对时间跨度以及消息条数做更严格的限制。


解释:这里本地缓存与平常使用的本地缓存,有一个最大区别,就是考虑了成本问题。


如果所有直播间的消息都进行缓存,假设同时有 1000 个直播间,每个直播间 5 种消息类型,本地缓存每隔 1 秒拉取一次数据,40 台前端机,那么对 Redis 的访问 QPS 是 1000 * 5 * 40 = 20 万。


成本太高,因此我们只有大直播间才自动开启本地缓存,小直播间不开启。


问题三:弹幕数据也支持回放,直播结束后,这些数据存放于 Redis 中,在回放时,会与直播的数据竞争 Redis 的 CPU 资源。


解决办法:


  • 直播结束后,数据备份到 MySQL;

  • 增加一组回放的 Redis;

  • 前端机增加回放的 local cache。


解释:回放时,读取数据顺序是: local cache -> Redis -> mysql。localcache 与回放 Redis 都可以只存某个直播某种消息类型的部分数据,有效控制容量;local cache 与回放 Redis 使用 sortedset 数据结构,这样整个系统的数据结构都保持一致。

二、高可用保障

  • 同城双机房部署

  • 双机房分为主机房和从机房,写入都在主机房,读取则由两个从机房分担。从而有效保证单机房故障时,能快速恢复。

  • 丰富的降级手段

  • 全链路的业务监控


高可用保障建设完成后,迎来了 TFBOYS 在美拍的四场直播,这四场直播峰值同时在线人数达到近百万,共 2860 万人次观看,2980 万评论,26.23 亿次点赞,直播期间,系统稳定运行,成功抗住压力。

三、使用长连接替换短连接轮询方案

  • 长连接整体架构图



详细说明:


  • 客户端在使用长连接前,会调用路由服务,获取连接层 IP,路由层特性:a.可以按照百分比灰度;b.可以对 uid,deviceId,版本进行黑白名单设置。黑名单:不允许使用长连接;白名单:即使长连接关闭或者不在灰度范围内,也允许使用长连接。这两个特性保证了我们长短连接切换的顺利进行;

  • 客户端的特性:a.同时支持长连接和短连接,可根据路由服务的配置来决定;b.自动降级,如果长连接同时三次连接不上,自动降级为短连接;c.自动上报长连接性能数据;

  • 连接层只负责与客户端保持长连接,没有任何推送的业务逻辑。从而大大减少了重启的次数,从而保持用户连接的稳定;

  • 推送层存储用户与直播间的订阅关系,负责具体推送。整个连接层与推送层与直播间业务无关,不需要感知到业务的变化;

  • 长连接业务模块用于用户进入直播间的验证工作;

  • 服务端之间的通讯使用基础研发团队研发的 tardis 框架来进行服务的调用,该框架基于 gRPC,使用 etcd 做服务发现。

长连接消息模型

我们采用了订阅推送模型,下图为基本的介绍:



举例说明,用户 1 订阅了 A 直播,A 直播有新的消息:


  • 推送层查询订阅关系后,知道有用户 1 订阅了 A 直播,同时知道用户 1 在连接层 1 这个节点上,那么就会告知连接层有新的消息;

  • 连接层 1 收到告知消息后,会等待一小段时间(毫秒级),再拉取一次用户 1 的消息,然后推送给用户 1。


如果是大直播间(订阅用户多),那么推送层与连接层的告知/拉取模型,就会自动降级为广播模型。如下图所示:



我们经历了客户端三个版本的迭代,实现了两端(Android 与 iOS)长连接对短连接的替换,因为有灰度和黑白名单的支持,替换非常平稳,用户无感知。

四、总结与展望

回顾了系统的发展过程,达到了原定的前中期使用轮询,中后期使用长连接的预定目标,实践了原定的平衡演进的原则。


从发展来看,未来计划要做的事情有:


针对机房在北京,南方某些地区会存在连接时间长的情况。我们如何让长连接更靠近用户;


消息模型的进一步演进。


作者介绍:


王静波,毕业于西安交通大学,曾任职于网易和新浪微博,微博工作期间负责开放平台业务和技术体系建设。2015 年 9 月加入美图,就职于架构平台部,目前负责部分核心业务和基础设施的研发工作,包括弹幕服务、Feed 服务、任务调度和质量监控体系等。十余年的后端研发经历,拥有丰富的后端研发经验,对于构建高可用、高并发的系统有较多实践经验。欢迎通过 wjb@meitu.com 跟他交流。


本文转载自美图技术公众号。


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


2020-02-24 19:154673

评论 1 条评论

发布
用户头像
你好,消息写入前端机是用什么通信方式?
2024-03-22 16:17 · 广东
回复
没有更多了
发现更多内容

一文说清楚数据集成中的流处理与批处理的区别

谷云科技RestCloud

Apache 数据处理 批处理 ETL 流处理

mes系统在新材料行业中的应用价值

万界星空科技

mes 万界星空科技 生产管理MES系统 新材料mes 新材料行业

对比传统数据库,TiDB 强在哪?谈谈 TiDB 的适应场景和产品能力

TiDB 社区干货传送门

品牌未来式,增长进行时|2024凯度BrandZ中国品牌盛典回顾

财见

支付宝携手HarmonyOS SDK打造高效便捷的扫码支付体验

HarmonyOS SDK

HarmonyOS

火山引擎VeDI核心产品DataTester再进化,A/B大模型应用评测功能上线

字节跳动数据平台

大数据 A/B 测试 对比实验 数字化增长

金蝶云·苍穹OEM版产品正式发布!AI时代共创软件产业新质生产力

金蝶云·苍穹

金蝶 生态伙伴 金蝶云苍穹

How to Add a Built-in Function to TiDB Using a Cursor in 20 Minutes

TiDB 社区干货传送门

TiDB 源码解读

TiDB 数据库核心原理与架构_Lesson 01 TiDB 数据库架构概述课程整理

TiDB 社区干货传送门

TiDB 底层架构

K1计划100%收购 MariaDB; TDSQL成为腾讯云核心战略产品; Oracle@AWS/Google/Azure发布

NineData

oracle 腾讯云 MariaDB tdsql K1

《黑神话:悟空》真的带火云电脑了吗?

脑极体

AI

MySQL 扛不住了,来试试这款平替的“国产化改造”必入手的国产数据库吧!

TiDB 社区干货传送门

是什么让 TiDB 从一款中国受欢迎的数据库产品在短短几年内成为全球受欢迎的数据库产品?

TiDB 社区干货传送门

手工转测试开发轻松实现薪资 50%涨幅的逆袭之路

测吧(北京)科技有限公司

测试

【黄金圆环】在研发领域的实践分享

京东科技开发者

电感生活So EZ 长安马自达MAZDA EZ-6全场景开放道路试驾

科技热闻

人工智能 | ChatGPT 插件开发

测吧(北京)科技有限公司

测试

SQL 中 Drop、Delete 与 Truncate 的区别

Chat2DB

数据库 开源 AI sql

全球布局、极速集成:IMkit搭建全面、快捷、安全的聊天应用

ZEGO即构

人工智能 即时通讯 IM UIKits imkit

万界星空科技MES系统如何实现设备数据集成

万界星空科技

数据采集 mes 设备管理 万界星空科技

非凸科技钻石赞助第四届Rust China Conf 2024

非凸科技

2024 医疗 Datathon 又叕来啦~!“理-工-医-信”跨学科联合科研,以数据驱动医疗实践

ModelWhale

R 语言 datathon 医疗大数据

TiDB在 G7 的实践和未来

TiDB 社区干货传送门

关于新版本 tidb dashboard API 调用说明

TiDB 社区干货传送门

集群管理 管理与运维 故障排查/诊断 新版本/特性解读 7.x 实践

超级驾趣学院 长安马自达MAZDA EZ-6驾驭全场景出行

极客天地

参与“2024,我想和 TDengine 谈谈”有奖征文活动,赢 AirPods

TDengine

数据库 tdengine 时序数据库

几张图带你了解TiDB架构演进

TiDB 社区干货传送门

版本升级

Serverless 安全新杀器:云安全中心护航容器安全

阿里巴巴云原生

阿里云 Serverless 云原生

NocoBase 与 NocoDB:开源无代码工具深度对比

NocoBase

开源 低代码 无代码开发 低代码开发 无代码

百万用户同时在线的高并发直播弹幕系统是如何实现的?_行业深度_王静波_InfoQ精选文章