如何设计一个 100W 用户同时在线的弹幕系统
行业案例:shopee 70W人在线的 弹幕 系统,是怎么架构的?
https://www.cyningsun.com/03-31-2019/live-streaming-danmaku.html
100W 用户在线, 3s 促达一次(将 3s 内的弹幕推送至用户)。 即 33w QPS 。
压力
- 带宽,33w QPS 的带宽是很大的
- 弱网环境
- 性能与可靠性
架构设计思路
- 业务解耦 + 服务拆分
- 将弹幕系统拆分为 2 个服务,发送弹幕(逻辑复杂,调用少)、弹幕拉取(逻辑简单,调用高)
- 本地缓存,优化高并发读
- 弹幕拉取服务,RPC 定时拉取数据,缓存至内存,后续请求到弹幕拉取服务时,直接走内存 (把数据放到离用户最近的地方)
- 本地缓存非常重要,推荐开源缓存框架 caffeine
- 限流,优化高并发写
- 发送弹幕限流(有选择丢弃多余的弹幕)
- 滑动窗口,实现无锁化读写
- 弹幕根据时间进行分片(按照秒数进行分片,只保留 60s 的数据)
- 根据请求时间戳,获取弹幕(30s 内的数据)
- 短轮训实现弹幕促达(推送 vs 拉取? 长轮训 vs 短轮训?)
- 长轮训、websocket(推送) 不适用弱网环境
- 采用短轮询
- 传输优化、节约带宽
- http gzip 压缩
- 结构体简化
- 请求频率控制
推送 vs 拉取, 长轮询 vs 短轮询
推送 push
服务器主动将数据推送至客户端,优点是实时性强,缺点是,服务器需要保持大量的长连接。
- websocket 双向
- SSE,单向
- 消息队列
拉取 pull
客户端主动向服务器请求数据,优点是,客户端控制请求时机,简单可靠。
- HTTP 请求
长轮询 Long Polling
客户端通过一个长连接请求服务器(发送请求到服务器之后,不断开连接,直到有数据,或者到了超时时间)
- Ajax Long Polling, 开启 http 的 keep-alive
短轮询 Short Polling
客户端频繁的请求服务器。使用的技术与长轮询一致,只是参数不同而已。