点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 8:55 更新文章,每天掉亿点点头发...

源码精品专栏

  • 原创 | Java 2020 超神之路,很肝~

  • 中文详细注释的开源项目

  • RPC 框架 Dubbo 源码解析

  • 网络应用框架 Netty 源码解析

  • 消息中间件 RocketMQ 源码解析

  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析

  • 作业调度中间件 Elastic-Job 源码解析

  • 分布式事务中间件 TCC-Transaction 源码解析

  • Eureka 和 Hystrix 源码解析

  • Java 并发源码

  • 前言

  • 直播弹幕系统

    • MVP版本

    • 缓存优化

    • 热点优化

    • 单元化架构

    • 客户端长连接推送

    • 弹幕回放

  • 总结


前言

直播业务现在特别火爆,也给人们的互动方式带来了很多新的改变,比如刷礼物、弹幕、排行榜等等。面对巨大的流量规模,直播技术的发展也备受关注。作为一个技术爱好者,相信你也会对直播的技术比较感兴趣,于是我去翻了几篇文章,了解了直播的技术方案,发现涉及到的技术细节太多,有部分已经是知识盲区,如音频、视频的编码传输等。

斗鱼:如何打造一个高性能、高可用直播系统架构

蘑菇街直播架构

直播相关知识之一-基本架构

直播中弹幕是一个非常亮眼和重要的功能,相比于秒杀架构,直播弹幕系统也有很多有趣的知识可以挖掘,一起来 YY 下如何设计一个直播弹幕系统,不对的地方还请有经验的大佬指出。

直播弹幕系统

直播弹幕是一个读写 QPS 要求都很高,假设一个直播间有 100w 用户同时在线观看,假设弹幕的提交频率为有 10000条/秒,那么需要每秒同时推送给在线用户的次数为 100w * 10000。由此可见,读请求的吞吐量需要远大于写请求,这点类似于 IM 实时聊天。、

架构设计考虑以下几个场景:

  • 支持直播弹幕回放

  • 用户进入直播间可以推送最新几秒的弹幕数据

  • 长连模式和短连模式可以做降级切换

MVP版本

为了不影响读写的性能,采用读写分离架构。

  • 写服务:若不考虑历史弹幕可回放,可以直接使用 Redis 作为唯一存储。若考虑支持弹幕的回放,数据还是需要持久化,可以考虑使用 MySQL 或者 TiDB,暂且认为写入不是较大的瓶颈。如果有更高性能的写需求,HBase、OpenTSDB 等都可以解决问题。

  • 读服务:Redis 主要用于读缓存,缓存直播间最新的弹幕数据,采用直播间 ID 作为 Key。系统读服务最大 QPS = Redis 集群QPS。

Redis 存储结构选择:SortedSet。

  • 提交弹幕:ZADD,score 设置为时间戳。进一步优化可以只存储时间的 delta 值,减少数据存储量。

  • 弹幕查询:ZRANGEBYSCORE 定时轮询弹幕数据。

有什么问题?

  • 系统性能与 Redis 集群容量强相关,性能提升需要扩容 Redis,成本高。

  • Redis 重复请求较多,相同直播间会存在很多重复的轮询请求。

缓存优化

如果能让最新的实时弹幕数据都能命中本地缓存,那性能是最高的,同时大幅度降低了 Redis 的读取压力。所以弹幕读服务可以每秒轮询 Redis 数据,构建本地缓存。

热点问题:

  • 假设同时在线的直播间有 10000 个,读服务机器有 50 台,那么每秒轮询 Redis 的 QPS = 10000 * 50 = 50w,读取请求线性膨胀。

  • 本地内存的使用量也随直播间的数量增长而膨胀,每个直播间的缓存的数据量降低,导致本地缓存的命中率降低,容易导致 GC 频繁。

热点优化

如何降低本地缓存的使用量?

  • 因为火爆的直播间会占据整个平台大部分的流量,可以只针对火爆的直播间开启本地缓存。

  • 通过路由控制同一个直播间的请求分发到固定的几台机器,例如一致性 Hash 算法。通过减少读服务机器上的直播间数量,达到降低本地缓存使用量的目的。

上述方法可以有效地解决问题,但是不能解决流量不均衡的问题。不同直播间分配的机器资源不是拍脑袋定的,需要有理论依据,可以根据直播间的一些数据指标进行动态分配机器资源。

  • 增加对直播间数据指标的统计,如单机 QPS、集群 QPS、单机直播间在线数等。

  • 关于自适应的负载均衡又是一个可以深挖的话题,在这里我们讨论几个常用的方案,有可能结合起来使用效果更好。

    • 分桶:不同 QPS 的范围段划分为不同的桶,根据桶范围的不同分配的机器数量也是不同的。

    • 最大最小公平分配:根据直播间的 QPS 划分资源需求的权重比例,根据总机器的数量和权重比例来分配机器数量。

    • 启发式算法:遗传算法、蚁群算法等。

单元化架构

单元化可以说是解决性能容量以及容灾的杀手锏。实现单元化需要完成有很多重要的工作,如数据同步 DRC、流量调度等,在此不作展开。

推荐一篇携程的 DRC 实践:携程异地多活-MySQL实时双向(多向)复制实践

客户端长连接推送

为了保障客户端消息的推送性能和实时性,长连接基本是必备的,最新的消息可以直接采用长连接实时推送。

  • Push Server 从 Redis 中获取用户和直播间的订阅关系以及长连接信息。

  • 连接代理只负责与客户端保持长连接。

  • 海量的消息推送需要批量压缩。

弹幕回放

增加一组专门用于回放的 Redis 集群,同时增加回放的本地缓存,其余设计与上述方案保持一致。

总结

抱着学习的心态,思考了直播弹幕系统的架构应该如何设计,本文主要讨论了以下几个点:

  • 读写分离的架构设计

  • 通过缓存优化读性能

  • 通过路由规则解决直播间流量不均衡的热点问题

  • 长连接的方案设计以及客户端的消息推送

暂时就 YY 这么多吧,做好一个系统还有需要细节需要考虑:高可用、监控、限流降级、延迟优化等。有什么错误和好的实践经验跪求留言。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

兄弟,一口,点个!????

假如让你从 0 到 1 实现一个直播弹幕系统相关推荐

  1. Swift3.0语言教程获得一个公共的前缀

    Swift3.0语言教程获得一个公共的前缀 Swift3.0语言教程获得一个公共的前缀,当在一个程序中有多个字符串时,我们需要判断是否有两个字符串有公共的前缀时,是很困难的.在NSString中的co ...

  2. 电脑安装android2.0,电脑上怎么安装使用安卓系统

    电脑上想要安装使用安卓系统,该怎么办呢吗,那么电脑上怎么安装使用安卓系统的呢?下面是学习啦小编收集整理的电脑上怎么安装使用安卓系统,希望对大家有帮助~~ 电脑上安装使用安卓系统的方法 工具/原料 Wi ...

  3. Java黑皮书课后题第4章:*4.11(十进制转十六进制)编写程序,提示用户输入0~15之间的一个整数,显示其对应的十六进制数。对于不正确的输入数字,提示非法输入

    *4.11(十进制转十六进制)编写程序,提示用户输入0~15之间的一个整数,显示其对应的十六进制数.对于不正确的输入数字,提示非法输入 题目 题目概述 运行示例 破题 代码 题目 题目概述 *4.11 ...

  4. Java黑皮书课后题第4章:*4.8(给出ASCII码对应的字符)编写程序,得到一个ASCII码的输入(0~27之间的一个整数),然后显示该字符

    *4.8(给出ASCII码对应的字符)编写程序,得到一个ASCII码的输入(0~27之间的一个整数),然后显示该字符 题目 题目概述 运行示例 引申 代码 题目 题目概述 *4.8(给出ASCII码对 ...

  5. Java黑皮书课后题第4章:*4.7(顶点坐标)假设一个正五边形的中心位于(0,0),其中一个点位于0点位置。编写程序,提示用户输入正五边形外接圆的半径,显示p1到p5的5个坐标,保留两位小数

    *4.7(顶点坐标)假设一个正五边形的中心位于(0,0),其中一个点位于0点位置.编写程序,提示用户输入正五边形外接圆的半径,显示p1到p5为5个坐标,保留两位小数 题目 题目概述 运行示例 破题 代 ...

  6. 从 0 开始手写一个 Spring MVC 框架,向高手进阶

    转载自   从 0 开始手写一个 Spring MVC 框架,向高手进阶 Spring框架对于Java后端程序员来说再熟悉不过了,以前只知道它用的反射实现的,但了解之后才知道有很多巧妙的设计在里面.如 ...

  7. 求两个数字的乘积,如果大于0,说明两个数字同号,如果小于0,说明两个数字异号,如果等于0,说明其中一个是0

    学了java基础东西,就写了这个编程,求两个数字的乘积,如果大于0,说明两个数字同号,如果小于0,说明两个数字异号,如果等于0,说明其中一个是0 首先程序要求我们输入两个数字,我就用了Scanner来 ...

  8. 要求将数组中的0项去掉,将不为0的值存入一个新的数组,

    package Day05;/*** 7.* 现在有如下一个数组:* int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5};* 要求将以上数组中的0项去掉,将不 ...

  9. python 速度 memmap_从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例

    <从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例>要点: 本文介绍了从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例,希望对您有用.如果有疑问,可 ...

  10. tinkphp1.0贺岁版小程序应用平台系统源码

    介绍: tinkphp1.0贺岁版小程序应用平台系统源码 安装说明:直接放入服务器或者空间,访问域名根据安装向导进行安装. 程序魅力:此程序是类似微信小程序一样的机制系统,但不是微信小程序,跟微信不搭 ...

最新文章

  1. 今日头条后端Java社招面经分享
  2. 白宫启动AI.GOV计划,呼吁各界携手共同推进AI发展
  3. 开源库OpenNMT-py使用记录
  4. 八十八、从斐波那契数列和零一背包问题探究动态规划
  5. Oracle用户创建及设置
  6. 蓝桥杯 ADV-87 算法提高 利息计算
  7. TensorFlow入门篇(二):线性回归
  8. 由href return false 来看阻止默认事件
  9. linux 指定jvm djava.library.path_JVM命令
  10. mysql 主从复制延迟_什么情况会导致MySQL主从复制延迟?
  11. 计算语言学和自然语言信息处理研究和应用综述(一)
  12. 《我的眼睛--图灵识别》第八章:训练:图像字符切割
  13. 可以快速提高编程能力的9个建议
  14. 计算机网络应用云计算,计算机网络云计算技术应用
  15. k8s 的容器command用法相关
  16. 关于Chrome不显示图片的问题
  17. 《手把手教你读财报》- 读书总结
  18. 大一新生必看,自学必看,里昂详解数据结构之二叉树
  19. 四色定理(DFS深搜)
  20. mysql查询数据库版本

热门文章

  1. 去除Multiple markers at this line - advised by提示
  2. Spring-AOP模块的Advised分析
  3. 三大框架整合开发的时候,出现红色双箭头,advised by org.springframework.transaction.interceptor.TransactionInterceptor.in
  4. 多双系统下蓝牙键盘鼠标的共享配对问题解决办法:win + debian + arch~IRK、LTK、ERand、EDIV、CSRK
  5. Safe Browsing API
  6. 2003年新版CCNP考试大纲---CITV5.0(转)
  7. AUTOSAR入门介绍
  8. 圆角半角数据库_数据库使用技巧――SQL 全角与半角切换_MySQL
  9. android实战开发记账本App,android开发实战-记账本APP(一)
  10. http响应码code含义