直播弹幕系统设计

本文仅提供思路参考,并非完备的详细设计。

特点

其实很类似IM即时通讯系统,是个变种,本质也是在一个空间内收发消息

  • 消息及时性强,过期消息意义不大
  • 用户松散,随时来随时走
  • 可能有瞬时大批量弹幕(比如比赛精彩部分)
  • 流量特点:读多写少

弹幕数据结构

type Bullet struct {
	UserId    int // 用户ID
	Content   string // 内容
	Timestamp int // 弹幕发送时间
	Extra     *Extra // 效果、样式
}

视频弹幕才有偏移时间,直播应该不用(因果一致性)

MVP版本

整体设计

读写分离架构,短连接+拉模式

  • 写:若不考虑历史弹幕可回放,可以直接使用 Redis 作为唯一存储
  • 读:Redis 主要用于读缓存,缓存直播间最新的弹幕数据

在这里插入图片描述

存储

数据结构选择Redis的ZSet

  • 需要弹幕按时间排序,而ZSet可保证有序
  • 此外,score允许重复,那我们就用timestamp来做score

使用

  • 发弹幕:ZADD 直播间ID, 弹幕val, timestamp(优化:时间只存相对于某个时间点的delta)
  • 拉取弹幕:ZRangeByScore 定时轮询(秒级,准实时即可)

问题

  1. 弹幕怎么持久化(Redis扩容成本高)
  2. 热门直播会有大量瞬时弹幕,挑战Redis并发瓶颈
  3. Redis重复请求多,相同直播间会存在很多重复的轮询请求

问题cover

  1. 持久化

    1. 若考虑支持弹幕的回放,数据还是需要持久化,可以考虑使用 MySQL

      1. 弹幕在直播结束后迁移至 DB(可以专门拿一台从redis做回放)
      2. 异步刷入(开线程/监听redis日志刷/发MQ消费)
    2. 如果有更高性能的写需求,可以考虑NoSQL DB,如:HBase、OpenTSDB 等

    3. 新问题:Write-Behind 这种以cache为主的模式,是可能会丢数据的

      1. DB挂了,少写数据,但是只要数据还在redis能追回来
      2. redis挂了,服务感知到后降级,请求回源,“缓存击穿”
  2. 使用MQ来消化瞬时弹幕,削峰;弹幕返回条数根据直播间的大小自动调整(热门直播间对时间跨度以及消息条数做更严格的限制)

  3. 对弹幕读请求,使用local cache缓存最近5s的数据在应用服务的内存中(过期了才回源redis)

    1. 新问题:如果直播间变多,本地内存使用量随直播间线性膨胀,本地cache的命中率下降,还可能频繁触发GC

    2. 解决:(1)只针对热门直播间使用本地cache使用“一致性hash”,控制同一直播间尽可能打到同一台服务器,降低本地cache使用量

优化:热门直播间

  • 需要对每个直播间进行指标采样

    • 标准:粉丝数、在线粉丝数、是否有活动
    • 弹幕系统需要与直播间系统隔离
    • 请求时带上直播间的“热门”标识
  • 根据服务器机器资源来分配所承载的热门直播间

长连接轮询

此前短连接的方式,每次轮询请求后都要重新建立连接。如果使用长连接轮询,客户端保持连接处于打开状态,就不会一直重新建立链接,减少重复的资源消耗,缩短响应时间。

不过,长连接轮询还是有一些缺点的:

  • 发送者和接收者可能并没有连接到同一个服务器

    • HTTP协议的服务器通常是无状态的,如果使用Round Robin的方式来做负载均衡,接收到弹幕的服务器可能并没有与等待接收消息的客户端保持长轮询连接
  • 服务器没有好的方法来判断客户端有没有断开连接

架构图

在这里插入图片描述

推模式

上面MVP版本是拉模式,适合前期;中后期规模和性能要求上来了,需要引入推模式。

架构图

在这里插入图片描述

长连接推送

为了保障客户端消息的推送性能和实时性,需要引入长连接

  • Push Server:负责推送(不感知直播业务)

    • 存储:从 Redis 中获取用户和直播间的关系以及长连接信息
    • 推送:分批并发推
  • connection proxy:只负责与客户端保持长连接

使用技术

  • WebSocket(HTTP 2.0支持的全双工通信+长连接)
  • Session(基于redis,通过用户会话来推)

优化

  • 有状态服务需要做好路由
  • 两个批量推送:消费 MQ 后批量推;从 push server 到连接代理的每个连接上也批量
  • 推拉结合,可以把短连接的拉作为长连接推的降级方案(服务端监控+客户端上报)

其他挑战

  • 写扩散(m条消息*n次扩散,平方级别)⇒ MQ控制推送速率
  • 丢弹幕 ⇒ push 失败引入重试;落 DB 引入 ACK
  • 带宽压力
  • 灰度拉切推

其他思路

  • 使用 redis 的 Stream 来做弹幕的发送(生产)和阅读(消费)
  • 前端展示上的优化
    • 弹幕去重
    • 发送弹幕后,本地优先展示(即使它丢了 or delay)

参考

  • https://cloud.tencent.com/developer/article/1645888
  • https://www.bilibili.com/video/BV1Uu411u7Cm/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/543618.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

漫途水产养殖水质智能监测方案,科技助力养殖业高效生产!

随着水产养殖业的蓬勃发展,水质和饲料等多重因素逐渐成为影响其持续健康发展的关键因素。由于传统养殖模式因监控和调节手段不足,往往造成养殖环境的恶化。需要通过智能化养殖,调控养殖环境,实现养殖的精细化管理模式,…

【Git教程】(九)版本标签 —— 创建、查看标签,标签的散列值,将标签添加到日志输出中,判断标签是否包含特定的提交 ~

Git教程 版本标签(tag) 1️⃣ 创建标签2️⃣ 查看存在的标签3️⃣ 标签的散列值4️⃣ 将标签添加到日志输出中5️⃣ 判断tag是否包含特定的提交🌾 总结 大多数项目都是用 1.7.3.2和 “ gingerbread” 这样的数字或名称来标识软件版本的。在 …

《由浅入深学习SAP财务》:第2章 总账模块 - 2.6 定期处理 - 2.6.6 年初操作:科目余额结转

2.6.6 年初操作:科目余额结转 在使用事务代码 FAGLB03 查询科目余额时,可以看到按期间的发生额清单。其中,第一行称为“余额结转”,该行的累计余额代表上年度遗留下来的余额,也就是年初余额。对于资产负债表科目而言&a…

中华人民共和国密码行业标准-各类标准文档下载

国家密码管理局 中华人民共和国密码行业标准 GmSSL Project 密码行业标准化技术委员会公布了所有密码行业标准,并支持全文查看,参见密码行业标准列表 GM/T 0001-2012 祖冲之序列密码算法 GM/T 0002-2012 SM4分组密码算法(原SMS4分组密码算法) GM/…

深度剖析整型和浮点型数据在内存中的存储(C语言)

目录 整型在内存中的存储 为什么整型在内存中存储的是补码? 大小端字节序 为什么有大端小端? 浮点型家族 浮点数在内存中的存储 long long 整型在内存中的存储 整型在内存中有三种二进制表示形式:原码,反码,补码…

Tomcat源码解析——Tomcat的启动流程

一、启动脚本 当我们在服务启动Tomcat时,都是通过执行startup.sh脚本启动。 在Tomcat的启动脚本startup.sh中,最终会去执行catalina.sh脚本,传递的参数是start。 在catalina.sh脚本中,前面是环境判断和初始化参数,最终…

Linux三剑客-sed、awk、egrep(上)

一、知识梗概 二、正则表达式 定义:正则表达式是一种强大的文本处理工具,用于在文本中搜索符合特定模式的字符串。它由一系列特殊字符和普通字符组成,可以定义复杂的搜索模式。正则表达式被广泛应用于各种编程语言和文本处理工具中。 简单来…

(2024,自回归,下一尺度预测,VQGAN)视觉自回归建模:通过下一尺度预测的可扩展的图像生成

Visual Autoregressive Modeling: Scalable Image Generation via Next-Scale Prediction 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 3. 方法 3.1 基础:通过下…

OpenAI反超Claude3,GPT4.5-Turbo正式版发布,AI王座再次易主

没想到,仅仅过了两个月,全球最强AI的宝座又易主了! 几个月前,Claude3 Opus全面超越GPT-4,全球的网友纷纷抛弃GPT,投向Claude3的怀抱,并纷纷分享Claude3带来的惊艳体验。 如今,Open…

Win10 使用Telnet

命令行 telnet 127.0.0.1 80 调试是否能连接服务 输入exit 回车即可退出 相比于ping的不同

k8s:kubectl 命令设置简写启用自动补全功能

k8s:kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes(K8s)是一个强大的容器编排平台&#xff0…

生活中的数学 --- 等额本息贷款和等额本金贷款的月供应该怎么算?

等额本息贷款和等额本金贷款的月供应该怎么算? 从一个例子开始,假设我要从银行贷款36万(即,本金),银行给出的贷款年利率是12%(月利率为年利率除以12),贷款半年(6个月),按月还款,分6期还完。 问分…

5、JVM-G1详解

G1收集器 -XX:UseG1GC G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征. G1将Java堆划分为多个大小相等的独立区域(Region),JVM目标…

Open CASCADE学习|实现Extrude功能

首先定义了一些基本的几何元素,如线、圆和平面,然后使用makeExtrudebydir函数来对一个面进行挤出操作。下面是详细过程: 定义Extrude函数:makeExtrudebydir函数接受一个TopoDS_Shape对象和一个gp_Vec对象作为参数。TopoDS_Shape是…

【数据挖掘】实验6:初级绘图

实验6:初级绘图 一:实验目的与要求 1:了解R语言中各种图形元素的添加方法,并能够灵活应用这些元素。 2:了解R语言中的各种图形函数,掌握常见图形的绘制方法。 二:实验内容 【直方图】 Eg.1&…

单路高清HDMI编码器JR-3211HD

产品简介: JR-3211HD单路高清HDMI编码器是专业的高清音视频编码产品,该产品具有支持1路高清HDMI音视频采集功能, 1路3.5MM独立外接音频输入,编码输出双码流H.264格式,音频MP3/AAC格式。编码码率可调,画面质…

CASA(Carnegie-Ames-Stanford Approach)模型原理及实践应用

植被作为陆地生态系统的重要组成部分对于生态环境功能的维持具有关键作用。植被净初级生产力(Net Primary Productivity, NPP)是指单位面积上绿色植被在单位时间内由光合作用生产的有机质总量扣除自养呼吸的剩余部分。植被NPP是表征陆地生态系统功能及可…

Linux登录访问限制

Linux系统下,用户密码的有效期可以通过编辑/etc/login.defs文件控制;密码复杂度规则设定需要通过/etc/pam.d/system-auth文件控制;登录失败次数限制通常由/etc/pam.d/login文件限制,可使用pam_tally2模块进行设置。 Linux系统下的…

Linux的学习之路:10、进程(2)

摘要 本章主要是说一下fork的一些用法、进程状态、优先级和环境变量。 目录 摘要 一、fork 1、fork的基本用法 2、分流 二、进程状态 三、优先级 四、环境变量 1、常见环境变量 2、和环境变量相关的命令 3、通过代码如何获取环境变量 五、导图 一、fork 1、fork…

Houdini笔记操作技巧_集锦

个人记录下,谨防遗忘。同时丰富下Hou的中文搜素环境。 1、自定义启动界面 ① 设置完界面后,保存自定义界面(Save Current Desktop As...) ② Edit-->Preferences-->General UIInterface-->Startup in Desktop&#xff1…