百万在线的美拍直播弹幕系统的实时推送技术实践之路

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 1、内容概述直播弹幕是直播系统的核心功能之一。如何迅速作出一个有很好扩展性的弹幕系统?如何应对业务迅速发展?相信很多工程师/架构师都有自己的想法。本文作者是美拍的架构师,经历了直播弹幕从无到有,从小到大的过程,借此文为大家分享构建弹幕系统的经验,希望能为正在开发或正打算开发弹幕、消息推送、IM聊天等系统的技术同行带来一些启发。

1、内容概述

直播弹幕是直播系统的核心功能之一。如何迅速作出一个有很好扩展性的弹幕系统?如何应对业务迅速发展?相信很多工程师/架构师都有自己的想法。

本文作者是美拍的架构师,经历了直播弹幕从无到有,从小到大的过程,借此文为大家分享构建弹幕系统的经验,希望能为正在开发或正打算开发弹幕、消息推送、IM聊天等系统的技术同行带来一些启发。

直播弹幕指直播间的用户,礼物,评论,点赞等消息,是直播间交互的重要手段。美拍直播弹幕系统从 2015 年 11 月到现在,经过了三个阶段的演进,目前能支撑百万用户同时在线。比较好地诠释了根据项目的发展阶段进行平衡演进的过程。这三个阶段分别是快速上线、高可用保障体系建设、长连接演进。具体我将在正文中展开,请继续往下阅读。

(本文同步发布于:http://www.52im.net/thread-1236-1-1.html

2、关于作者

王静波

- 毕业于西安交通大学,曾任职于网易和新浪微博,微博工作期间负责开放平台业务和技术体系建设;

- 2015年9月加入美图,就职于架构平台部,目前负责部分核心业务和基础设施的研发,包括弹幕、Feed、任务调度和质量监控体系等;

- 十余年的后端研发经历,拥有丰富的后端研发经验,对于构建高可用、高并发的系统有较多实践经验。

3、起步——快速上线

3.1 消息模型

美拍直播弹幕系统在设计初期的核心要求是:

1)快速上线;

2)并能支撑百万用户同时在线。

基于这两点,我们策略是前中期 HTTP 轮询方案,中后期替换为长连接方案。因此在业务团队进行 HTTP 方案研发的同时,基础研发团队也紧锣密鼓地开发长连接系统。

直播间消息,相对于IM即时通讯的场景,有其几个特点:

1)消息要求更及时:过时的消息对于用户来说不重要;

2)松散的群聊:用户随时进群,随时退群;

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

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

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

2)接收直播间持续接收弹幕消息;

3)自己发消息。

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

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

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

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

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

因此总的流程是:

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

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

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

如上图所示,某个用户从第6号评论开始拉取,同时有两个用户在发表评论,分别是10,11号评论。如果11号评论先写入,用户刚好把6,7,8,9,11号拉走,用户下次再拉取消息,就从12号开始拉取,结果是:用户没有看到10号消息。

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

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

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

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

4、问题——上线后暴露的问题及解决方法

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

4.1 问题一:消息串行写入 Redis,容易堆积在 Kafka 中且消息延迟较大

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

解决办法:

1)消息写入流程优化:前端机-> Kafka -> 处理机 -> Redis;

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

3)处理机:如果延迟小,加锁串行写入 Redis;如果延迟大,则取消锁。因此有四种组合,四个档位,分别是:

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

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

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

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

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

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

4.2 问题二:redis slave 的性能瓶颈较大

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

解决办法:

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

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

解释:

这里本地缓存与平常使用的本地缓存问题,有一个最大区别:成本问题。如果所有直播间的消息都进行缓存,假设同时有1000个直播间,每个直播间5种消息类型,本地缓存每隔1秒拉取一次数据,40台前端机,那么对 Redis 的访问QPS是   1000 * 5 * 40 = 20万。成本太高,因此我们只有大直播间才自动开启本地缓存,小直播间不开启。

4.3 问题三:弹幕数据回放时,会与直播的数据竞争 Redis 的 cpu 资源

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

解决办法:

1)直播结束后,数据备份到 mysql;

2)增加一组回放的 Redis;

3)前端机增加回放的 local cache。

解释:

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

5、升级1——实现高可用保障

同城双机房部署:

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

丰富的降级手段:

全链路的业务监控:

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

6、升级2——使用长连接替换短连接轮询方案

6.1 长连接架构

长连接整体架构图如下:

详细说明:

1)客户端在使用长连接前,会调用路由服务,获取连接层IP,路由层特性(a. 可以按照百分比灰度;b. 可以对 uid、deviceId、版本进行黑白名单设置):

  - 黑名单:不允许使用长连接;

  - 白名单:即使长连接关闭或者不在灰度范围内,也允许使用长连接。

这两个特性保证了我们长短连接切换的顺利进行。

2)客户端的特性:

  - a. 同时支持长连接和短连接,可根据路由服务的配置来决定;

  - b. 自动降级,如果长连接同时三次连接不上,自动降级为短连接;

  - c. 自动上报长连接性能数据;

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

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

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

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

6.2 长连接消息模型

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

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

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

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

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

如下图所示:

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

7、总结与展望

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

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

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

2)消息模型的进一步演进。

(本文同步发布于:http://www.52im.net/thread-1236-1-1.html

附录:更多推送技术文章

iOS的推送服务APNs详解:设计思路、技术原理及缺陷等

信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑

Android端消息推送总结:实现原理、心跳保活、遇到的问题等

扫盲贴:认识MQTT通信协议

一个基于MQTT通信协议的完整Android推送Demo

IBM技术经理访谈:MQTT协议的制定历程、发展现状等

求教android消息推送:GCM、XMPP、MQTT三种方案的优劣

移动端实时消息推送技术浅析

扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别

绝对干货:基于Netty实现海量接入的推送服务技术要点

移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)

为何微信、QQ这样的IM工具不使用GCM服务推送消息?

极光推送系统大规模高并发架构的技术实践分享

从HTTP到MQTT:一个基于位置服务的APP数据通信实践概述

魅族2500万长连接的实时消息推送架构的技术实践分享

专访魅族架构师:海量长连接的实时消息推送系统的心得体会

深入的聊聊Android消息推送这件小事

基于WebSocket实现Hybrid移动应用的消息推送实践(含代码示例)

一个基于长连接的安全可扩展的订阅/推送服务实现思路

实践分享:如何构建一套高可用的移动端消息推送系统?

Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)

腾讯信鸽技术分享:百亿级实时消息推送的实战经验

百万在线的美拍直播弹幕系统的实时推送技术实践之路

>>更多同类文章 ……

(本文同步发布于:http://www.52im.net/thread-1236-1-1.html

目录
相关文章
|
9月前
|
数据挖掘
直播平台源码开发,信息收发功能搭建
信息发送消息实现代码 import java.util.ArrayList; import java.util.List; 信息接收消息实现代码 public void receiveMessage() { System.out.println("接收消息:");
直播平台源码开发,信息收发功能搭建
|
10月前
|
存储 缓存 监控
直播系统聊天技术(九):千万级实时直播弹幕的技术实践
疫情期间,线上演唱会是一种很常见的直播娱乐形式,由于线下社交距离的限制,线上形式演唱会比以往更火爆,而对技术的要求也更高。 本文基于网易云信针对TFBOYS某场线上演唱会的技术支持,为你分享千万级在线用户量的直播系统中实时弹幕功能的技术实践,希望能带给你启发。
230 0
|
运维 Cloud Native 容器
【直播】直播预告 | 云原生游戏第4讲:游戏服的网络接入和状态管理【直播已生成回放】
2022 年 11 月 29 日(周二)阿里云容器服务高级工程师 & 云原生游戏负责人,刘秋阳将会为大家详细介绍 OKG 的网络插件功能,一键式部署游戏服南北向网络,OKG 的自定义服务质量功能,以及自动化地感知并管理游戏服状态。
【直播】直播预告 | 云原生游戏第4讲:游戏服的网络接入和状态管理【直播已生成回放】
|
前端开发
语音直播系统源码,加速平台流量变现的重要功能
语音直播系统源码,加速平台流量变现的重要功能
|
数据采集 JSON 自然语言处理
手把手教你实现『B站直播』弹幕实时分析
大家好,我是阿辰,今天来教大家如何实现『B站直播』弹幕实时分析 思路:采集直播弹幕,然后通过情感分析,不同时间点的评论数,高频词统计
450 0
|
Web App开发 人工智能 编解码
声网:如何自研支撑百万用户的毫秒级实时音视频系统?
大规模实时音视频(RTC)是疫情时代火热的在线课堂、直播、电话会议等的技术基础,但对于多数工程师来说,自研 RTC 系统的架构设计在客户端、服务端、运维、测试和质量监控上仍存在很多难点。因此我们整理了 QCon 全球软件开发大会(2021)北京站上,声网 Agora 行业架构师董海冰分享的三部分内容:RTC(实时音视频)的基础概念、场景及特点分析;自研 RTC 的架构设计和难点;展望 RTC 未来,帮你扣开实时音视频系统架构设计的大门。以下为老师分享的正文。(下文以董海冰老师第一人称叙述)
672 0
声网:如何自研支撑百万用户的毫秒级实时音视频系统?
|
人工智能 边缘计算 文字识别
跨境电商直播实时字幕,如何做到 “实时”?
2020 的双 11 狂潮已然提早,年度氪金剁手大会已吹响号角。
跨境电商直播实时字幕,如何做到 “实时”?
|
编解码 算法 开发工具
直播泛在化的今天, 如何快速搭建不同场景的直播系统
目前,不同的直播业务场景的直播需求越来越多,不同的直播需求对应着不同的技术侧重点。本篇演讲将通过介绍阿里云的直播技术架构,从客户的角度讲解如何集成阿里云的直播产品,描绘在阿里云视频云直播系统内进行快速的场景搭建效果,展示其直播系统的技术特点。
直播泛在化的今天, 如何快速搭建不同场景的直播系统
|
运维 Java 视频直播
一对一源码开发,一对一直播系统如何在直播领域站稳脚跟
在直播发展的过程中,开发系统的直播源码也发展的越来越成熟稳定,尤其是目前很火热的一对一源码。
一对一源码开发,一对一直播系统如何在直播领域站稳脚跟