| 量级 | 说明 |
|---|---|
| 单机 10 w TPS | 内存 + Netty + 环形队列 |
| 集群 100 w TPS | 分片写 + 本地缓存 + 推流合并 |
| 实现要点(10 行代码级) |
写链路
用户→Netty 网关→本地 RingBuffer(Disruptor)→批量 50 条/10 ms→Kafka(partition = roomId % N)读链路
① 拉:客户端 HTTP/getDanmu?roomId=123&startId=1000返回 200 条
② 推:WebSocket 长连,服务端每 200 ms 合并广播一次(gzip)存储
热数据:Redis Listdanmu:123存 500 条,LRU 淘汰
冷数据:Kafka→Flink→ClickHouse,按天表归档关键优化
• 本地缓存: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。