直播间弹幕系统是典型的高并发、高吞吐、低延迟场景。面对“每秒百万级弹幕”的极端场景,核心矛盾在于 海量并发写入 vs 有限的客户端接收能力

1. 核心挑战与设计原则

  • 上行压力 (Write): 假设每秒 100 万条弹幕写入,数据库和带宽压力极大。
  • 下行压力 (Push): 假设 1000 万在线用户,如果全量推送,每秒需推送 次消息,带宽成本天价且客户端根本处理不过来。
  • 实时性: 弹幕必须低延迟,否则用户体验极差。

核心原则: 服务端限流、聚合、智能丢弃。用户肉眼每秒只能看清 10-20 条弹幕,全推过去既浪费带宽也毫无意义。

2. 总体架构设计

采用 读写分离 + 推拉结合 + 分桶策略 的架构。

2.1 接入层 (Gateway)

  • 协议: WebSocket 长连接 (全双工,低延迟)。
  • 技术栈: Go (Goroutine) 或 Java (Netty),单机支撑 10w+ 连接。
  • 职责: 维持用户连接,鉴权,心跳保活。

2.2 逻辑层 (Logic)

  • 职责: 业务处理(敏感词过滤、鉴黄)、持久化、消息分发。
  • 削峰: 使用 Kafka 消息队列缓冲上行流量,保护下游存储。

2.3 存储层 (Storage)

  • 实时缓存: Redis Sorted Set (按时间戳排序),用于短时间内的历史弹幕回溯。
  • 持久化: HBase / Cassandra / TiDB (写多读少,支持海量数据写入)。

3. 关键优化策略

3.1 消息分桶 (Bucket) / 房间分片

这是解决“广播风暴”的核心手段。

  • 原理: 将一个大直播间 (RoomID=8888) 拆分为多个虚拟桶 (Bucket_1, Bucket_2, … Bucket_N)。
  • 路由: 用户进入直播间时,通过 Hash 或 负载均衡 算法随机分配到一个 Bucket 中。
  • 分发策略:
    • 普通弹幕: 只在 当前 Bucket 内广播。用户 A 在 Bucket_1 发弹幕,只有 Bucket_1 的用户能看到。
    • 高优弹幕 (礼物/系统公告): 全房间广播 (所有 Bucket)。
  • 效果: 将 1000 万人的广播风暴拆解为 100 个 10 万人的小广播,大幅降低下行压力。

3.2 智能丢弃 (Smart Shedding) & 限流

当弹幕 QPS 超过阈值时,必须进行有损服务。

  • 优先级队列:
    1. : 礼物、付费弹幕、系统公告 (必须送达)。
    2. : 进场特效、关注提示。
    3. : 普通文本弹幕。
  • 丢弃策略:
    • 当缓冲区满或 QPS 超限时,优先丢弃低优先级消息
    • 采样: 每秒只随机保留 10-20 条普通弹幕推送给客户端,其余的只入库存档,不推送。

3.3 消息合并 (Batching)

  • 原理: 服务端不要来一条推一条。
  • 实现: 将 100ms-500ms 内的弹幕聚合为一个 Batch 包,一次性推给客户端。
  • 效果: 大幅减少 TCP 包头开销和网络 IO 次数,提升压缩率。

3.4 客户端优化

  • 渲染: 使用 Canvas 或 WebGL 渲染弹幕,避免大量 DOM 操作导致的页面卡顿。
  • 对象复用: 建立弹幕对象池 (Object Pool),避免频繁 GC。
  • 丢弃: 如果客户端积压过多未渲染弹幕,直接清空队列,跳到最新。

4. 极端场景下的降级方案

  1. 关闭普通弹幕: 压力过大时,只允许发送和推送礼物/付费弹幕。
  2. 拉模式 (Pull) 兜底: 如果推送服务挂了,客户端降级为每 3-5 秒轮询一次 HTTP 接口获取弹幕 (虽然体验差,但能保证可用)。
  3. 熔断非核心服务: 暂停点赞数统计、即时榜单更新,资源优先保直播流和核心弹幕。

5. 总结

挑战解决方案
海量写入Kafka 削峰、HBase/TiDB 写优化
广播风暴分桶策略 (Bucket)、消息合并 (Batching)
客户端卡顿智能丢弃 (Shedding)、Canvas 渲染
高可用降级、熔断、多级缓存