直播是「实时性、规模、互动」三重压力叠加的系统:主播端一路推流,几十万观众同时拉流,还要支持连麦、弹幕、送礼这些实时互动。它和点播最大的区别是——内容在产生的那一刻就要被分发出去,没有转码完再发布的缓冲窗口,任何环节的延迟都会直接反映在观众体验上。本文按照系统设计面试的标准答题结构,设计一个生产级的直播系统。
一句话:直播系统的两条主线是「低延迟分发」与「高并发互动」——推流链路决定了延迟下限,互动链路决定了规模上限,两者对基础设施的要求截然不同。
一、需求澄清与量级估算
1.1 需求澄清
面试官给出题目「设计一个直播系统」后,先通过提问明确边界:
- 直播类型:秀场直播、游戏直播、电商直播、教育直播、还是低延迟互动直播(连麦 PK)?类型决定延迟要求。
- 延迟要求:普通秀场可接受 3
5 秒;电商直播希望 13 秒;连麦 PK 要求 400ms 以内。延迟要求直接决定协议选型。 - 互动能力:弹幕、点赞、送礼、连麦、连麦 PK、观众上麦,支持到哪一层?
- 规模:单房间峰值观众数?是「少量大房间」(如明星演唱会百万在线)还是「大量小房间」(如秀场几千房间各几百人)?
- 清晰度:支持几档码率?是否需要 1080p60?
- 内容安全:是否需要实时审核(鉴黄、涉政)、延迟几秒内可封禁?
- 录制与回放:是否要边播边录、结束后生成回放?
1.2 量级估算
以一个中等直播平台为例:
日活观众: 3000 万
同时在线房间: 5 万(秀场为主)
单房间平均观众: 60 人,头部房间可达 10 万+
峰值同时观看: 500 万
主播推流码率: 4 Mbps(1080p)
单主播上行带宽: 5 万 × 4Mbps = 200 Gbps(入)
观众下行带宽: 500 万 × 平均 2Mbps = 10 Tbps(出,靠 CDN 分摊)
弹幕 QPS: 500 万在线 × 人均 0.2 条/分钟 ≈ 1.7 万条/秒(峰值 ×5 ≈ 8.5 万/秒)
礼物消息 QPS: 峰值 2 万/秒(大促/大主播带货时)
连麦房间: 约 1% 房间同时连麦 → 500 个并发连麦房
关键结论:下行带宽是最大的成本项(10 Tbps 必须靠 CDN 分摊),弹幕是最大的 QPS 来源(8.5 万/秒),而推流上行的房间数相对稳定(5 万路)。三个数字指向三套不同的技术栈:推流用长连接接入层、分发用 CDN、弹幕用长连接广播层。
二、高层架构设计
主播 ──RTMP/SRT推流──▶ ┌────────────────┐
│ 推流接入集群 │ 鉴权 / 断流检测
│ (边缘节点) │
└───────┬────────┘
▼
┌────────────────┐
│ 转码集群 │ 多码率 / 实时审核
│ (GPU + 审核) │ 截帧送审
└───────┬────────┘
▼
┌────────────────┐
│ 源站 (Origin) │ 切片 / 封装
│ HLS/DASH/FLV │
└───────┬────────┘
▼
┌────────────────────────┐
│ CDN 边缘节点(回源拉流) │
└───────────┬────────────┘
▼
┌────────────────┐
│ 观众播放器 │ HLS/FLV/WebRTC
└───────┬────────┘
│ 弹幕/礼物/连麦信令
▼
┌────────────────┐
│ 互动长连接集群 │ 弹幕广播 / 房间状态
│ (WebSocket) │
└───────┬────────┘
▼
┌────────────────┐
│ 连麦信令 (SFU) │ WebRTC 媒体转发
└────────────────┘
四条关键链路:
- 推流链路:主播 RTMP/SRT 推流到接入节点,鉴权通过后转发到转码集群。
- 转码链路:转出多档码率并实时截帧送内容审核,审核通过才允许分发。
- 分发链路:源站切片封装成 HLS/FLV,CDN 边缘回源拉流并缓存,观众就近拉取。
- 互动链路:观众通过 WebSocket 长连接发弹幕、礼物,服务端广播到同房间所有连接;连麦走 WebRTC SFU。
三、核心组件设计
3.1 推流接入与鉴权
协议选型:
RTMP: 老牌直播协议,基于 TCP,延迟 1~3 秒,主播端支持最广,但浏览器已不支持(需 Flash 或转封装)
SRT: 基于 UDP,抗丢包强,适合弱网推流,延迟 200~500ms,OBS 已支持
RTSP: 安防/IPC 常用,直播平台少用
WebRTC: 浏览器直接推流,延迟 < 500ms,但码率与稳定性弱于 SRT
实践组合:主播端 RTMP 为主(兼容性最好),弱网/移动端用 SRT,浏览器开播用 WebRTC。接入层要同时支持多协议,统一转成内部格式。
推流鉴权:防止盗推(别人拿你的推流地址乱推)与盗播(未授权拉流)。
推流鉴权(URL 签名):
推流地址 = rtmp://push.example.com/live/{stream_key}?txSecret={md5}&txTime={expire}
txSecret = MD5(secret_key + stream_key + txTime_hex)
接入节点校验:重算 txSecret 是否匹配、txTime 是否过期
拉流鉴权(防盗链):
播放地址 = https://cdn.example.com/live/{stream_key}.m3u8?auth_key={sign}&expire={ts}
CDN 边缘校验签名,防止第三方站点盗用你的带宽
断流检测与重连:
class StreamSession:
def on_publish(self, stream_key, conn):
if not verify_sign(stream_key, conn.query):
conn.close(); return
self.sessions[stream_key] = {"conn": conn, "last_frame": now()}
def heartbeat_check(self):
"""定时扫描:超过 5 秒没收到媒体帧视为断流"""
for key, s in list(self.sessions.items()):
if now() - s["last_frame"] > 5:
self.on_disconnect(key)
def on_disconnect(self, key):
# 通知业务:主播断流 → 房间状态置为「暂离」,保留 30 秒等待重连
self.sessions.pop(key, None)
room.set_state(key, "TEMPORARILY_OFFLINE", grace=30)
重连的体验设计:主播网络抖动断流时,不要立刻把房间标记为「已结束」——保留一个宽限期(如 30 秒),期间观众看到「主播网络不稳定」提示而非直接黑屏退出。宽限期内主播重连,无缝恢复;超时才真正结束直播。
推流质量监控:接入节点要持续采集主播端的推流质量(码率、帧率、丢包率、卡顿次数),异常时主动通知主播「当前网络差,建议降低码率」,并支持服务端下发「降码率指令」。这套「客户端上报 + 服务端决策」的模式与 WebRTC 低延迟直播 里的网络自适应完全同源。
3.2 转码与低延迟分发
转码的实时性约束:点播转码可以慢慢来,直播转码必须「边收边转边发」,任何积压都会变成观众端的延迟累积。
实时转码流水线:
接收帧 → 解码 → [可选:缩放/水印/审核截帧] → 编码 → 切片/封装 → 推送源站
延迟预算:单次转码延迟必须 < 200ms,否则多档叠加会拖慢整体
关键参数(以 HLS 为例):
分片时长:2 秒(传统 HLS 是 6~10 秒,直播要更短)
GOP 长度:2 秒(与分片对齐,保证可无缝切换)
转码 preset:veryfast / ultrafast(速度优先,画质次之)
多码率阶梯:与点播类似,但直播通常只做 3~4 档(观众带宽有限、切档要快)。
480p 800 kbps
720p 1800 kbps
1080p 3500 kbps
低延迟协议选型:这是直播系统最关键的决策。
协议 延迟 兼容性 成本 适用场景
HLS 6~30 秒 最好(原生) 低(CDN) 普通秀场、录播兼容
LL-HLS 2~5 秒 较好 中 电商直播、互动要求较高
FLV/HTTP-FLV 1~3 秒 需 flv.js 低 国内直播主流
WebRTC 200~500ms 需信令 高(SFU) 连麦、PK、强互动
SRT 200~500ms 需专用播放器 中 专业推流/回传
工程上的常见组合:默认 FLV(1~3 秒)覆盖大多数观众,连麦时切 WebRTC,弱网或旧设备降级 HLS。协议的切换对观众要透明——播放器探测到 WebRTC 不可用就自动回落到 FLV。
CDN 回源与分发:
源站(Origin): 只服务 CDN 边缘的回源请求,不直接对观众
边缘节点: 就近缓存分片,命中率 > 95%
回源策略:
- 分片文件(.ts/.flv 段):长缓存(如 60 秒,直播分片用完即弃)
- 清单文件(.m3u8):极短缓存(1~2 秒),否则观众拿不到最新分片
- 回源请求合并:同一分片的并发回源合并成一个(防回源风暴)
边缘回源失败: 重试其他边缘 / 回上级节点 / 最终回源站
首帧优化:观众点进直播间最在意「多久出画面」。优化手段包括:CDN 预取(进房间前先拉清单)、起始档位选择(按历史带宽直接选合适档位,避免从最低档爬升)、GOP 缓存(边缘缓存一个 GOP,观众进来立刻发一个完整 GOP 出画面)。
3.3 连麦与信令
连麦的本质:把两路(或多路)主播的音视频实时混流后分发给观众。技术选型上,一对一或小房间用 SFU(Selective Forwarding Unit)——服务器只做转发不做混流,客户端各自解码多路。
SFU 架构(以 1v1 PK 为例):
主播 A ──推流──▶ SFU ──转发──▶ 主播 B
主播 B ──推流──▶ SFU ──转发──▶ 主播 A
│
└──合成/分别转发──▶ 观众(看到 A+B 画面)
为什么用 SFU 而不是 MCU(服务器混流):
SFU:服务器只转发,CPU 开销小,可扩展;客户端解码多路,对观众设备有要求
MCU:服务器混流成一路,观众只解码一路;但服务器 CPU 开销大,成本高
直播场景观众端多,通常「主播间 SFU 转发 + 对观众侧做混流」混合使用
信令流程:
1. 主播 A 发起连麦邀请 → 信令服务记录邀请状态
2. 主播 B 接受 → 双方交换 SDP(offer/answer),协商编解码与传输参数
3. 双方通过 ICE 收集候选地址(STUN/TURN),建立媒体通道
4. 媒体经 SFU 转发,观众侧订阅合成流
5. 结束连麦 → 释放媒体通道,房间回到单人直播状态
信令必须可靠有序(用 WebSocket 或可靠消息通道),而媒体走 WebRTC 的 UDP 通道——信令丢了连麦就建不起来,媒体丢几帧只影响画质。这种「控制面可靠、数据面尽力」的分离是所有实时通信系统的通用原则,WebRTC SFU/MCU 架构 里有更深入的拓扑讨论。
房间状态同步:连麦房间的状态(谁在麦上、谁在排队、谁被踢出)是强一致的,不能出现「两个人同时以为自己拿到了麦位」。用「房间状态机 + 乐观锁」管理:
def take_mic(room_id, user_id, expected_version):
# 条件更新:只有版本号匹配才能抢到麦位
rows = db.execute(
"UPDATE live_room SET mic_user=%s, version=version+1 "
"WHERE room_id=%s AND mic_user IS NULL AND version=%s",
(user_id, room_id, expected_version))
if rows == 0:
raise MicTaken() # 麦位已被他人占用
publish_event(MicTaken(room_id, user_id))
连麦的质量保障:连麦对延迟和丢包最敏感。措施包括:优先用 SRT/WebRTC(UDP 抗丢包)、开启 FEC 前向纠错、动态码率(网络差时降码率保流畅)、以及对音频做优先保障(丢视频帧可以,丢音频不行)。
3.4 弹幕与消息风暴
弹幕的规模挑战:一个大主播房间可能有 10 万在线,每人每分钟发 0.2 条弹幕,就是每秒 333 条;峰值(抽奖、大事件)可达每秒上万条。系统要同时做到「低延迟广播」与「不被打垮」。
长连接广播架构:
观众 ──WebSocket──▶ 接入网关(无状态,可水平扩展)
│
▼
┌──────────────┐
│ 房间消息总线 │ Redis Pub/Sub 或 MQ
│ (按 room_id) │
└──────┬───────┘
▼
各接入网关订阅自己承载房间的消息 → 推给本地连接
关键点:
1. 接入网关按 room_id 分片订阅,避免「每个网关订阅所有房间」
2. 一个房间的连接可能分散在多个网关 → 消息要广播到所有承载该房间的网关
3. 网关维护「本地房间 → 连接集合」的映射,收到消息后本地扇出
削峰与降级:弹幕是「可丢弃」的——丢掉 10% 的弹幕用户基本无感,但系统不能挂。所以弹幕链路要设计成分层降级:
第 1 层:客户端本地限流(同一用户 1 秒最多发 3 条)
第 2 层:网关限流(单连接 10 条/秒,单房间 1 万条/秒)
第 3 层:服务端采样(房间消息量超阈值时,按比例采样广播,如只广播 50%)
第 4 层:分级广播(大房间只广播「高价值弹幕」:带礼物的、主播回复的、房管的)
第 5 层:熔断(极端情况下关闭弹幕,只保留礼物与系统消息)
「分级广播」是直播弹幕最实用的技巧:10 万人的房间不需要让每个人都看到每一条弹幕,观众看到的弹幕流是「采样 + 优先级」的结果。这与 弹幕系统设计 里的「消息分级 + 采样 + 批量合并」策略一致。
礼物消息不能丢:与弹幕相反,礼物消息涉及金钱,必须可靠、有序、不重复。
礼物链路:
观众送礼 → 扣款(幂等)→ 生成礼物事件 → 持久化 → 广播特效 + 计入榜单
要求:
1. 扣款幂等(幂等键防重复扣)
2. 事件持久化(用于对账、榜单、主播分成)
3. 广播可降级(特效可以不显示,但账必须记对)
礼物与弹幕走不同的优先级队列:礼物 P0(可靠 + 优先),弹幕 P2(可丢弃)。这与 消息队列系统设计 里的优先级队列与背压机制同构。
弹幕的存储:弹幕量大且价值低,不需要长期保存(除非录播需要)。做法是「热存内存 + 冷存采样」:内存里保留最近 N 条供新进房间的观众补全历史,落库只存采样后的少量数据(如每 10 秒存 1 条)供事后分析。
内容审核的实时性:弹幕与直播画面都要实时审核。画面审核靠截帧送审(每秒 1~2 帧),弹幕审核靠「敏感词过滤 + 机器分类 + 人工兜底」。审核有延迟,所以策略是「先发后审 + 命中即撤回」——弹幕先广播,审核命中后下发撤回指令删除。这与 内容审核系统设计 的「先放行后拦截 + 可撤回」模型一致。
四、深入权衡
1. 延迟与成本的权衡:延迟越低,成本越高。HLS 延迟 10 秒但 CDN 成本极低(分片可缓存、可分发到最便宜的边缘);WebRTC 延迟 300ms 但要自建 SFU 集群、每路连接都占资源。所以绝大多数观众走 FLV/HLS,只有连麦主播走 WebRTC。
2. 转码档位与成本:多一档码率就多一份转码算力与存储。直播通常只做 3 档,且用 GPU 转码(快),画质略逊于 CPU 但直播可接受。
3. 弹幕的完整性 vs 系统稳定:理论上可以保证「所有弹幕不丢」,但代价是海量长连接与广播带宽。绝大多数平台选择「采样 + 分级」,用少量丢弹幕换取系统在热点事件下不崩。
4. 单房间 vs 多房间的架构差异:大量小房间(秀场)适合「网关按房间分片 + 房间消息总线」;少量超大房间(演唱会)适合「专用集群 + 边缘广播 + 强采样」。两种形态的容量模型完全不同,平台常需同时支持。
5. 内容安全与实时性的冲突:实时审核有延迟,若「审后发」会让直播画面延迟数秒(不可接受),所以只能「先发后审 + 快速封禁」。这意味着必须接受「违规内容可能短暂可见」的风险,用「封禁响应时间」而非「零违规」作为指标。
五、总结
直播系统的设计可以浓缩成四条主线:
- 推流接入是入口:多协议(RTMP/SRT/WebRTC)支持 + URL 签名鉴权 + 断流宽限期重连,守住内容源。
- 延迟由协议决定:HLS/FLV/LL-HLS/WebRTC 构成延迟-成本谱系,按场景组合选型,观众侧透明降级。
- 连麦靠信令与 SFU:控制面(信令)可靠有序,数据面(媒体)尽力而为,房间状态用乐观锁保证麦位唯一。
- 弹幕分级、礼物可靠:弹幕可采样可丢弃用分层降级,礼物必须幂等扣款 + 持久化,两条链路优先级截然不同。
延伸阅读:弹幕广播的分级与采样策略见 弹幕系统设计 ;连麦房间的长连接与消息同步见 即时通讯系统设计 ;低延迟媒体传输与 SFU 拓扑见 WebRTC 低延迟直播 与 WebRTC SFU/MCU 架构 ;直播画面的实时审核见 内容审核系统设计 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。