Skip to content
量级说明
单机 10 w TPS内存 + Netty + 环形队列
集群 100 w TPS分片写 + 本地缓存 + 推流合并
实现要点(10 行代码级)
  1. 写链路
    用户→Netty 网关→本地 RingBuffer(Disruptor)→批量 50 条/10 ms→Kafka(partition = roomId % N)

  2. 读链路
    ① 拉:客户端 HTTP /getDanmu?roomId=123&startId=1000 返回 200 条
    ② 推:WebSocket 长连,服务端每 200 ms 合并广播一次(gzip)

  3. 存储
    热数据:Redis List danmu:123 存 500 条,LRU 淘汰
    冷数据:Kafka→Flink→ClickHouse,按天表归档

  4. 关键优化
    • 本地缓存:Caffeine 缓存最近 5 秒弹幕,80% 读命中
    • 合并写:同一房间 10 ms 内的弹幕打包一次 Redis LPUSH
    • 流量整形:Sentinel 限制单房间 5 k/s,超量直接丢弃,优先保证看播流畅

核心代码

java
// Netty 收到一条弹幕
Channel channel = ctx.channel();
long seq = ringBuffer.next();
try {
    DanmuEvent event = ringBuffer.get(seq);
    event.setRoomId(roomId).setContent(msg);
} finally {
    ringBuffer.publish(seq);
}

// 消费者批量落 Redis
public void onEvent(List<DANMU> batch) {
    if (batch.isEmpty()) return;
    String key = "danmu:" + batch.get(0).getRoomId();
    redisTemplate.opsForList().leftPushAll(key, batch);
    redisTemplate.expire(key, 5, TimeUnit.MINUTES);
}

数据
线上 8 核 16 G 单节点压测 12 w TPS,P99 延迟 11 ms;
3 节点集群 + 10 分片 Kafka 可稳定 80 w TPS,峰值 100 w TPS。