粉丝1056获赞14.5万

昨天帮一个四年经验的粉丝复盘腾讯二面工程师官问了他个真实业务场景题平台某档综艺直播开播的时候,开播瞬间海量观众同时发弹幕,属于典型顺时高并发, 后端要求必须一步入库一步推送给直播间在线用户,绝对不能同步阻塞接口。你说说这种直播弹幕高并发场景, 怎么保证弹幕不丢失不重复推送?同时还要做好接口限流防刷?他开始自信,这题很基础啊。这个简单,用消息队列啊, cuf 或者 rocket mark q, 所有弹幕先写 mq, 消费者亦不处理。不丢失的话, 把 mq 的 持久化打开 ack 确认机制配好,重复推送就在消费端做密等。比如用 read 存已处理的消息 id 限流防刷,用令牌桶或者漏桶算法 ingis 层就能配。他跟我讲到这我就知道他面试肯定在了。 不只是他,我发现很多人跟这位粉丝一样,只懂皮毛架构套模板这里我特意整理了扎挖后端面试高频提库加完整架构落地笔记加项目合集。如果你是我的粉丝,学习区敲个面试我发你。果然面试官反问,你管这叫精通高并发? 那我再问细一点,跑男弹幕场景用户发一条弹幕,你后端要生成一个局唯一的消息 id 对 吧?这个 id 在 高并发下怎么生成? 如果用分布式 id, 性能瓶颈在哪?你说密等用 reddis 存 id, 那 几十万 qps 写 reddis 网卡和内存扛得住吗?过期策略怎么设?弹幕推送给几百万人?你是每条弹幕都推全量在线用户吗?它开始卡壳 id 生成,可以用雪花算法 每个节点自己生成, reddis 存储的话可以设置短一点过期时间,比如一小时弹幕场景,时效性强,推送的话可以推给在线的活跃用户子集。 面试官打断,雪花算法强,依赖机器时钟,时钟回拨了你怎么办?你说推活跃资金,那怎么定义活跃? 刚进直播间的人之前弹幕没收到,体验怎么保证?还有,如果 m q 挂了,生产者直接拒绝写入弹幕就丢了,你怎么办?他明显慌了,那可以用本地内存队列暂存, m q 恢复后再发送。 面试官摇摇头,本地内存重启就没了,你考虑过此盘缓冲吗?还有限流防刷,如果用户一秒刷一百条弹幕,你是直接拒绝还是允许拒绝的?弹幕算不算丢失?用户投诉怎么办?他沉默两秒,这个 可能要产品和运营定策略,端到端数据一致性你 你就答不上来了。高并发症不是配个 m q 就 叫方案丢失重复,限流防刷这四个词,每个背后都有一堆坑。面试结束,这场面试,这位粉丝暴露的问题, 其实百分之九十的面试者都会犯,知道用 m q, 但不知道 m q 挂了怎么办?知道密等,但不知道百万级 q p s 下 rad 怎么扛?下面我直接给你核心拆解。 一、弹幕不丢失,不止 m q 持久化。一、多级缓冲写入客户端 api 网关,网关异步发送到 m q, m q 选型 rocket miller 或 posar, 开启同步刷盘加同步双写。 极端情况, m q 集群全部不可用,网关降级为本地磁盘对列定时重试。二、生产者端的防丢失闭环,每个弹幕生成唯一 id, 生产者同步返回已接收给客户端。 失败场景,客户端重试加去重。三、全链路超时与重试生产者 m q 同步发送失败,亦不落本地重试表 m q 消费者消费失败,重试队列加死信队列,人工兜底。二、不重复推送,层层的密等和去重。一、写入去重用户 id 加弹幕内容, hash 加时间窗口 read 中 set next, 过期时间五秒 命中则直接拒绝,不生成消息 id。 二、消费密等,消费者落数据库时用 message id 做唯一锁影,捕获重复异常直接跳过。 为什么不用 reddis 存已消费 id 百万 qps 下 reddis 网络开销太大,用数据库唯一锁影加批量插入性能更高。三、推送去重 推送服务维护,每个用户最近收到的弹幕 id 最小堆,收到重复直接丢弃,因为推送到客户端走 redback 无法保证。 exactly once, 靠客户端和服务端双重去重。三、接口限流,防刷分维度多级柔性,具体看下方图标 关键点,限流不是简单拒绝,如果是普通用户刷屏直接拒绝并返回四二九告知发送过快,如果是疑似机器静默丢弃,避免对抗。四、异步推送到几百万人 不报概宽不大全量核心原则,推拉结合加分层聚合。一、弹幕推送,不是每条推全量每秒产生的弹幕先聚合,按时间窗口合并成一个小批次 批次推送到直播间弹幕网关,网关根据用户连接的 websel 节点删除。二、 分层推送架构,生产者在平衡层消费者组,消费者将批次写入房间弹幕缓存,用户连接时先拉取最近两百条缓存弹幕,再订阅增量推送。三,推送贷宽优化。二禁止协议代替 jason 同房间用户共享增量批次,推送时只广播批次 id 客户端本地渲染冷用户改走轮询拉取,降低 webcel 连接数。

