Jack Jiang

我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
posts - 525, comments - 13, trackbacks - 0, articles - 1

2025年11月25日

本文由B站技术团队比奇堡、Xd、三木森分享,有修订和重新排版。

1、引言

本文要分享的是B站IM消息系统的新架构升级实践总结,内容包括原架构的问题分析,新架构的整体设计以及具体的升级实现等。

cover-opti

B站技术团队的其它技术文章:

  1. B站千万级长连接实时消息系统的架构设计与实践
  2. B站实时视频直播技术实践和音视频知识入门
  3. B站基于微服务的API网关从0到1的演进之路

2、消息系统业务解读

1和2

按业务全域现状,在服务端角度分成客服系统、系统通知、互动通知和私信4个业务线,每个业务线内按现状标识了服务分层。私信内分为用户单聊、bToC的批量私信、群聊和应援团小助手四类,这四类细分私信没有技术解耦,单聊和批量私信比较接近系统天花板。

2

私信单聊发送到触达的pv转化和uv转化不足10%,有明显通过业务优化提升触达率的潜力。

3、消息系统中的私信业务

私信域内的几个概念解释:

1)会话列表:按聊天人排序的列表。即B站首页右上角信封一跳后看到的历史聊天人列表,以及点击未关注人等折叠会话看到的同属一类的聊天人列表。传达对方账号、最新私信和未读数的信息。点击一个会话后看到的是对聊历史,也称会话历史。

2)会话详情:描述和一个聊天人会话状态的原子概念,包括接收人uid、发送人uid、未读数、会话状态、会话排序位置等。

3)会话历史:按时间线对发送内容排序的列表。一份单聊会话历史既属于自己,也属于另一个和自己的聊天的人。群聊的会话历史属于该群,不属于某个成员。会话历史是收件箱和消息内容合并后的结果。

4)收件箱:将一次发送的时序位置映射到发送内容唯一id的kv存储,可以让服务端按时间序读取一批发送内容唯一id。

5)私信内容:一个包括发送内容唯一id、原始输入内容、消息状态的原子概念。批量私信把同一个发送内容唯一id写入每个收信人的收件箱里。

6)timeline模型:时间轴的抽象模型,模型包括消息体、已读位点、最大位点、生产者、消费者等基本模块,可以用于基于时间轴的数据同步、存储和索引。私信涉及timeline模型的包括会话列表和会话历史。

7)读扩散:pull模式。群聊每条私信只往群收件箱写一次,让成百上千的群成员在自己的设备都看到,是典型的读扩散。

8)写扩散:push模式。单聊每条私信既更新接收人会话也更新发送人会话,是轻微的写扩散,无系统压力。群聊有另一个不一样的特点,就是当群成员发送消息后,需要通过长链接通知其他群成员的在线设备,以及发送人其他的在线设备,这是一个写扩散的技术模型,但是这个写扩散是通知后即时销毁的,并且具有过期时间,所以仅临时占用资源,并不对存储造成压力,且能有较好的并发量。

私信核心概念关系表达:

3

4、消息系统问题1:会话慢查询

当会话缓存过期时,Mysql是唯一回源,Mysql能承载的瞬时QPS受当时应用总连接数和sql平均响应速度的影响,连接数打满时会给前端返回空会话列表。虽然可以增加POD数量、增大akso proxy连接数、优化sql和索引来作为短线方案,来提升瞬时请求Mysql容量,但是这种短线方案无法加快单次响应速度,mysql响应越来越慢的的问题依然在。另外增加POD数量也会降低发版速度。

4

会话Mysql使用用户uid%1000/100分库,用户uid%100分表,table总量是1000。

单表会话量在1kw-3.2kw。单个大up的会话积累了10W条以上,会话量最大的用户有0.2亿条会话。单个Up的会话会落到一张表中,每张表都有比较严重的数据倾斜。如果考虑增加分库分表的方案,sql查找条件依然需要用户uid,所以相当于倾斜数据要转移到新的单表,问题没有解决。另外,重新分库分表过程中新旧table增量同步和迁移业务读写流量的复杂度也很大,有比较大的业务风险。

Mysql的规格是48C 128G和32C 64G。由于会话数据量大,Mysql buffer_pool有限,数据比较容易从内存淘汰,然后mysql需要进行磁盘扫描并将需要的数据加载到内存进行运算,加之比较多的磁盘扫描数据,这时的响应一般在秒级别,接口会给前端返回超时错误,会话列表页空白。

为了适配业务发展,Mysql 会话表 已经添加了9个非聚集索引,如果通过增加索引使用业务需要,需要更大的Mysql资源,且解决不了冷数据慢查询的问题。增加更多索引也会让Mysql写入更慢。

5、消息系统问题2:私信内容单表空间和写性能接近天花板

每条私信内容都绑定私信自己的发号器生成的msgkey,即私信内容唯一id,该msgkey包含私信发送时的时间戳(消息ID生成可参阅读《微信的海量IM聊天消息序列号生成实践》)。读写私信内容Mysql之前先从msgkey解析出时间,用这个时间路由分库分表。

私信内容库按季度分库,分库内按月度分表,单表数据量数亿,数据量最大的用户日增私信351.9W条。按照曲率预测,25年全年数据量有近百亿,如果继续按照月度分表,分表规则不适应增长。

当前该Mysql最大写qps 790,特别活动时写qps峰值预计是20k,但是为了保障Mysql服务整体的可靠,单库写流量我们需要控制在3000qps以下,无法满足写入量峰值时的需要。

5

此外,消息内容表结构包含了群聊、单聊和应援团小助手全部的属性,增加业务使用难度。绝大部分私信内容是单聊的。

6、消息系统问题3:服务端代码耦合

B站的四类私信包括:

  • 1)单聊;
  • 2)群聊;
  • 3)B端批量私信;
  • 4)应援团小助手。

这些私信都需要实现发送和触达两条核心链路,四种私信核心链路的代码逻辑和存储耦合在一起,代码复杂度随着业务功能上线而不断增加,熵增需要得到控制。

从微服务这方面来说,实例和存储耦合会带来资源随机竞争,当一方流量上涨,可能给对方的业务性能带来不必要的影响,也会带来不必要的变更传导。

7、消息系统新架构的升级路径

基于对私信现状的论述,可以确定我们要优化的是一个数据密集型 >> 计算密集型,读多写少(首页未读数)、读少写多(会话)场景兼具的系统。

同时需要拥有热门C端产品的稳定性、扩展性和好的业务域解耦。针对读多写少和读少写多制定了针对的技术方案。

具体的实施情况请继续往下阅读。

8、新架构的整体设计

结合B站业务现状,我觉得比较合理的架构:

6

一个兼顾复杂列表查询架构和IM架构的消息域框架,整体分四层:

  • 1)接入层:即toC的BFF和服务端网关;
  • 2)业务层:按复杂查询设计系统,用于各种业务形态的支撑;
  • 3)平台层:按IM架构设计系统,目标是实时、有序的触达用户,平台层可扩展;
  • 4)触达层:对接长链和push。

9、新架构具体升级1:端上本地缓存降级

端上应该支持部分数据缓存,以确保极端情况下用户端可展示,可以是仅核心场景,比如支付小助手、官号通知,用户在任何情况下打开消息页都不应该白屏。

10、新架构具体升级2:BFF架构升级

BFF网关吸收上浮的业务逻辑,控制需求向核心领域传导。服务端基于业务领域的能力边界,抽象出单聊、群聊、系统通知、互动通知和消息设置共五个新服务,提升微服务健康度。

7

新服务剥离了历史包袱,也解决一些在老服务难解的功能case,优化了用户体验,比如消息页不同类型消息的功能一致性;重新设计会话缓存结构和更新机制,优化Mysql索引,优化Mysql查询语句,减少了一个量级的慢查询。

8

11、新架构具体升级3:服务端可用性升级

11.1 概述

服务端按四层拆分后,集中精力优化业务层和平台层。

业务层:按复杂查询设计系统,用于各种业务形态的支撑

  • 1)冷热分离:多级缓存 redis(核心数据有过期)+taishan(有限明细数据)+mysql(全部数据);
  • 2)读写分离:95%以上复杂查询可以迁移到从库读。

平台层:按IM架构设计系统,目标是实时、有序的触达用户,平台层可扩展

  • 1)Timeline模型:依赖雪花发号器,成熟方案;
  • 2)读写扩散:单聊-写扩散,群聊-读扩散。

11.2 单聊会话

1)缓存主动预热:

用户在首页获取未读数是一个业务域内可以捕捉的事件,通过异步消费这个事件通知服务端创建会话缓存,提高用户查看会话的缓存命中率。鉴于大部分人打开B站并不会进私信,此处可以仅大UP预热。大UP的uid集合可以在数平离线分析会话数据后写入泰山表,这个泰山表更新时效是T+1。

监控UP会话数量实时热点,触发突增阈值时,通过异步链路自动为热点用户主动预热会话列表缓存。

对预热成功率添加监控,并在数平离线任务失败或者预热失败时做出业务告警,及时排查原因,避免功能失效。

2)泰山和Mysql双持久化:

增加泰山存储用户有限会话明细,作为redis未命中后的第一回源选择,Mysql作为泰山之后的次选。基于用户翻页长度分析后确定泰山存储的有限会话的量级。

9

redis 存储24小时数据,taishan 存储 600条/用户(20页),预设到的极端情况才会回源mysql从库。

对于ZSET和KV两种数据结构,评估了各自读写性能的可靠性,符合业务预期。业务如果新增会话类型,可以跟本次新增泰山有限明细一样,基于会话类型的具体规则新增泰山Key。

10

3)泰山长尾优化:

查询redis未命中时会优先回源泰山,考虑到泰山99分位线在50ms以下,而且Mysql多从实例都能承受来自C端的读请求,所以采用比泰山报错后降级Mysql稍微激进的对冲回源策略。

在泰山出现“长尾”请求时,取得比较好的耗时优化效果。可以使用大仓提供的error group结合quit channel实现该回源策略,同时能避免协程泄漏。整个处理过程在业务响应和资源开销中维持中间的平衡,等待泰山的时间可以灵活调整。

11

泰山最初没有数据,可以在泰山未命中时进行被动加载,保证用户回访时能命中。

4)一致性保证:

虽然我们重构了新服务,但是老服务也需要保留,用来处理未接入BFF的移动端老版本和web端请求,这些前端在更新会话时(比如ACK)请求到了老服务,新服务需要通过订阅会话Mysql binlog异步更新本服务的redis和泰山。为了避免分区倾斜,订阅binlog的dts任务使用id分区,这样方便的是一条会话在topic的分区是固定的。

为了避免两次请求分别命中泰山和Mysql时给用户返回的数据不一样,需要解决三大问题:

  • a. 当出现分区rebalance需要避免重复消费;
  • b. 当Mysql一条会话记录在短时间内(秒级)多次更新,要保证binlog处理器不会逆时间序消费同一个会话的binlog,即跳过较早版本的binlog;
  • c. 保证泰山写入正确并且从Mysql低延迟同步。

这三个问题都要保证最终一致性,具体解决方案是用redis lua脚本实现compare and swap,lua脚本具有原生的原子性优势。dts每同步一条binlog都会携带毫秒级mtime,当binlog被采用时,mtime被记入redis10分钟,如果下一条binlog的mtime大于redis记录的mtime,这条binlog被采用,否则被丢弃。

这个过程可以考虑使用gtid代替mtime,但这个存在的问题是每个从实例单独维护自己的gtid,当特殊情况发生mysql主从切换,或者dts订阅的从节点发生变更,gtid在CAS计算中变得不再可靠,所以我们选择了使用mtime作为Mysql会话记录的版本。

通过消费路线高性能设计保证泰山异步更新的延迟在1秒以内,并在特殊情况延迟突破1s时有效告警。高性能消费路线中,每个库的binlog分片到50个partition,业务提供不低于50个消费pod,单pod配置100并发数,按照写泰山999分位线20ms计算,每秒可以消费 50*100*(1000/20)=250000 条,大约线上峰值8.3倍,考虑dts本身的max延迟在600~700毫秒,同步泰山和redis的延迟会在700毫秒至1秒以内,符合业务预期。

12

11.3 收件箱

BFF已经从业务层和平台层将单聊读收件箱独立出来,本次升级主要是从存储做增量解耦 ,存量单聊收件箱的读流量可以访问旧表。 单聊新收件箱存储采用redis+泰山的模式,redis提供热数据,泰山提供全部数据并采用RANDOM读模式,让主副本都能分担读流量。

13

 

11.4 私信内容

本次升级主要如下:

  • 1)单聊增量数据独立存储,按照单聊业务设计表结构,和群聊、应援团小助手彻底解耦。
  • 2)写Mysql升级为异步化操作,提高写性能天花板,这种异步写Mysql改造不会影响读消息内容的可用性和设计。
  • 3)单聊分库规则升级为月度分库,单库内分表为100张。 群聊、应援团小助手和历史单聊依然使用旧的分库分表规则读写Mysql。

业务需要对增量单聊私信路由分库分表时,先从msgkey先解析出时间戳,找到用时间戳对应的月份分库,然后用msgkey对100取余找到分表。这种方案能达到按时间纬度的冷热数据的分离,同时由于msgkey取余的结果具有随机性,平衡了每张表的读写流量。这样预计2025年单表数据量能从9亿下降到900万。

14
15

11.5 批量私信

日常通道:日常批量私信任务共用通道,共用配额。

高优通道:主要通过将链路上topic partition扩容、消费POD扩容、POD内消费通道数扩容、缓存扩容、akso proxy连接数扩容,把平均发送速度从3500 人/秒提高到30000人/秒。这个通道可以特殊时期开给特殊业务使用。

12、本文小结

我们逐步发现技术升级不是一蹴而就的,它是一个逐步优化的过程。

设计技术方案前设立合适和有一些挑战的目标,但这个目标要控制成本,做好可行性。

设计技术方案的时候,需要清楚现有架构与理想架构的差距和具体差异点,做多个方案选型,并确定一个,这个更多从技术团队考虑。

其次要保证功能在新老架构平稳过渡,保证业务的稳定性。后面持续关注新老架构的技术数据,持续优化,老架构要持续关注它的收敛替换。

IM系统是一个老生常谈的话题,也是融合众多有趣技术难点的地方,欢迎感兴趣的同行交流研讨。

13、参考资料

[1] 浅谈IM系统的架构设计

[2] 简述移动端IM开发的那些坑:架构设计、通信协议和客户端

[3] 一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

[4] 一套原创分布式即时通讯(IM)系统理论架构方案

[5] 从零到卓越:京东客服即时通讯系统的技术架构演进历程

[6] 蘑菇街即时通讯/IM服务器开发之架构选择

[7] 微信技术总监谈架构:微信之道——大道至简(演讲全文)

[8] 现代IM系统中聊天消息的同步和存储方案探讨

[9] 子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

[10] 一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践

[11] 从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路

[12] 瓜子IM智能客服系统的数据架构设计(整理自现场演讲,有配套PPT)

[13] 阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处

[14] 阿里技术分享:电商IM消息平台,在群聊、直播场景下的技术实践

[15] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

[16] 从新手到专家:如何设计一套亿级消息量的分布式IM系统

[17] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

[18] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制

[19] 阿里IM技术分享(三):闲鱼亿级IM消息系统的架构演进之路

[20] 基于实践:一套百万消息量小规模IM系统技术要点总结

[21] 跟着源码学IM(十):基于Netty,搭建高性能IM集群(含技术思路+源码)

[22] 一套十万级TPS的IM综合消息系统的架构实践与思考

[23] 得物从0到1自研客服IM系统的技术实践之路

[24] 一套分布式IM即时通讯系统的技术选型和架构设计

[25] 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗

[26] 转转平台IM系统架构设计与实践(一):整体架构设计

[27] 支持百万人超大群聊的Web端IM架构设计与实践

[28] 转转客服IM聊天系统背后的技术挑战和实践分享

即时通讯技术学习:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

(本文已同步发布于:http://www.52im.net/thread-4886-1-1.html

posted @ 2026-01-06 17:34 Jack Jiang 阅读(20) | 评论 (0)编辑 收藏

     摘要: 本文由45岁老架构师尼恩分享,感谢作者,有修订和重新排版。1、引言你有没有想过,为什么 ChatGPT 的回答能逐字逐句地“流”出来?这一切的背后,都离不开一项关键技术——SSE(Server-Sent Events)! 本文从SSE(Server-Sent Events)技术的原理到示例代码,为你通俗易懂的讲解SSE技术的方方面面。2、A...  阅读全文

posted @ 2025-12-23 15:07 Jack Jiang 阅读(39) | 评论 (0)编辑 收藏

本文由腾讯技术团队颜勇分享,原题“腾讯新闻PUSH架构升级之路”,有修订和重新排版。

1、引言

68 万行代码精简到8.6 万;Golang 重写大部分 C++模块;解决过度微服务化问题…… 这是新闻 PUSH 架构团队取得的技术收益。

PUSH 是腾讯新闻精品资讯的重要分发途径,也是新闻 App 重要的促活手段。作为 PUSH 架构团队,我们一方面在积极支持好新闻护盘,同时也在对 PUSH 架构进行不断的升级与进化,以持续提升 PUSH 系统的稳定性与质量、研发效率,同时持续减少运营成本。

本文主要分享的是腾讯技术团队近年来对腾讯新闻消息推送PUSH系统做的架构优化和技术实践。

cover-opti

2、Push平台介绍

2.1 概述

PUSH 是腾讯新闻内容重要的分发渠道,新闻 PUSH 平台承担着将新闻资讯触达到新闻用户、满足用户及时获取精品资讯的需求。

1

总体上,新闻 PUSH 链路分为下面两部分。

2.2 PUSH触发

按触发方式的不同,新闻 PUSH 分为三类:

  • 1)人工 PUSH:运营在 push cms 系统指定要发送的文章、要触达的人群包,人工触发push发送;这类 PUSH 目前主要用于推送热点事件/热点资讯等;
  • 2)自动化 PUSH:周期性地给用户计算他可能感兴趣的内容,这类推送由后台自动触发;
  • 3)功能性 PUSH:由业务系统触发,主要是为了实现一些业务功能通知,比如评论通知、关注通知等。

2.3 PUSH下发

对于所有 PUSH 触发 的PUSH 进行调度(包括避让、打散和频控等)和触达(通过自有通道或厂商通道推送给用户)。

新闻业务对新闻 PUSH 平台最重要的要求是:

1)要保证精品咨讯触达的及时性:

新闻 PUSH 最重要的是要体现“新”,因为腾讯新闻用户有及时获取热点/突发资讯的诉求,用户经常有这样的体感,有热点突发事件时,所有 App 都会尝试第一时间向用户发起推送,用户大概率会点击收到的第一个推送。在了解了相关热点事件后,对于后续其它 App 的推送,对用户而言就没信息量了,大概率会被忽略,甚至可能会被用户视为一种打扰,影响用户体验。从我们实验数据来看,当P USH 下发延迟降低 50%,PUSH 点击量会提升 10%。

所以新闻 PUSH 一直以来的目标是:热点资讯需要第一时间触达给用户,要做到“全网首推”。

2)要保证推送的用户体验和较好的拉起效率:

PUSH 是新闻重要的促活手段,需要有较好的促活效率,这要求保证用户较好的推送体验,因为用户如果感觉推送体验不好,用脚投票,把 App 的 PUSH 系统开关给关了,这对 PUSH 而言就基本上就永远丧失了给这个用户推送的机会了。这就要求要尽量保证在合适的时间点给推送用户感兴趣的内容,推送要有合理的频次,相邻 PUSH 之间要有合理的时间间隔,推送内容要做合适的打散。

其实这两个要求其实在一定层面上是有冲突的:

  • a.如果要保证推送的及时性,就要求尽量减少计算,拿到消息消息后无脑推到消息通道,这个肯定最快;
  • b.如果要保证良好的推送用户体验,就需要做很多的判断、考量和计算,这些考虑越多就需要做更多的计算和 io 操作,会影响推送的及时性;最近几年,业务成本的考虑也是 PUSH 关注的重点,需要削减使用的机器和资源,就要求用更少的机器如何发得更快更好。

总结而言,之前新闻 PUSH 业务的突出问题主要有两个方面,请继续往下阅读。

3、Push平台问题1:推送速度慢

我们团队从 2022 年年中开始接手新闻 PUSH 平台。交接工作刚启动,就遇到了一次 S 级热点事件——一个国际级突发新闻。那天晚上,全网用户都在密切关注它的最新进展。

这个事件有两个特点:热度极高、且并非完全突发——早在一个月前就已经有明确预告,因此运营部门提前布置了应急预案。我们刚接手系统时,对整个下发链路还不够熟悉,只能凭直觉扩容机器,希望能抗住峰值。结果现实很快给了我们一记当头棒喝。

当晚,很多内部同事都装着多个新闻 App,一眼能看到谁家的推送更快。那晚我们的延迟问题非常明显,甚至有用户在热点过去一个多小时后才收到通知。事后有专门的评测团队做了分析,指出“PUSH 下发耗时过长,高活用户 P90 均值达 20 分钟”,报告还发到了高层群里——对我们来说,那无疑是一次刻骨铭心的教训。

4、Push平台问题2:开发效率和问题排查效率低

之前 PUSH 链路特别长,新闻 PUSH 内部有 30+ 个模块,同时还依赖其它两个跨业务团队。经常一个需求开发要改多个模块,要团队几个人一起开发,约定交互协议,开发后再联调测试,在多个模块起联合实验;然后还得给中台提需求,然后匹配中台的排期后,才能完成需求上线;这一系列操作就拉长了 push 需求的leadtime。

线上有 case 时,问题排查也需要串联多个模块,关联多个模块数据,甚至需要跨部门拉上其它这边来一起来排查,排查效率非常低。push case 非常多,比如用户为什么收到了/没收到某条 push 之类的典型 case,之前需要关联链路20来个模块的日志,还要联合中台一起排查,每次 case 排查时间都在天级;之前在case 排查上,每天都耗费我们大量的人力。

既要持续提升 PUSH 触达的及时性、又要持续提升推送的用户体验和拉活效率,还要持续降低运营成本,客观而言,在技术上是一个较大的挑战。本文主要详述,我们如何通过技术架构升级来支撑这个既要&又要&还要的目标。

5、老Push架构的问题梳理

5.1 模块链路过长,内耗过多

一条快速PUSH,从推送内容过审后,到最终发出去,最长要经过18个模块,另外还需要经过中台多个模块。一条待推送的数据最多要经历 17 次内部 rpc 转发,多个模块之间腾挪流转,各种网络 rpc,各种内耗,肯定发得慢。

一个最典型的例子:原架构有个模块叫scheduler,它主要负责决定一个push该不该发,直观上感觉它里面应该囊括了各种过滤策略,但是原架构做成了多个微服务。scheduler 模块里本身有一些过滤逻辑,另外有一个叫做 filter 的模块,专门负责品牌、开关等硬规则过滤;另外有一个叫做 policy 的模块,专门负责配额等软规则过滤;所有过滤规则都通过后,进入一个叫做 channer 模块,就决定下这次推送走哪个通道;然后又走到一个叫 worker 的模块里,而它只做对接下游中台的协议适配。

总体上看,原链路就是过度微服务化了:

  • 1)模块多会导致数据流转的低效,模块间网络 rpc 会浪费处理耗时;
  • 2)其次会影响迭代效率,模块数不是越多越好,因为经常一个需求需要改多个模块,做多次上线;
  • 3)同时模块过多也对联调&测试效率,影响线上 case 排查效率。

这就违反了“模块内高内聚,模块间低耦合”的架构设计原则,进而会影响业务迭代效率。

5.2 依赖服务有瓶颈

上文提到的 S 级热点事件时,我们将下发服务机器扩了一倍,但是下发速度并没有提升,说明瓶颈不在下发服务本身下,而是在依赖服务上;通过链路debug,我们定位到了链路瓶颈:号码包拉取。

在发送人工 push,运营会指定受众人群包(几百万到几亿不等),这时候需要分页拉取该号码包数据进行处理。

之前老架构使用了底层平台的人群包服务,新闻所有 push 人群包都上传到了该人群包服务,当发送指定人群包,需要请求平台侧接口分页拉取人群包数据,当时因为平台侧人群包功能实现比较复杂,能支持一些比较高级的能力,因此这个分页接口耗时比较长。但其实我们只用到了最简单的数据分页的功能,完全可以采用更简单的实现方案,以减少接口耗时。

5.3 链路稳定性不好

5.3.1)容错能力差:

之前链路基本无容错能力,发生了过一次因上游未按约定协议跟我们请求交互,导致我们服务挂了半天,是一次典型的 P0 级事故。

5.3.2)缺少节点自动故障转移:

scheduler 负责 push 调度,原架构为了提升处理效率,scheduler 里做了本地缓存;为了避免缓存失效,起了一个服务 dispatch 消费触发侧生产的待推送的消息,然后按照用户设备号一致性哈希来 sharding,通过 rpc 请求对应的 scheduler,scheduler接受到请求后,塞入到它本地的内存队列里,如果队列满了就直接丢弃。

它原来存在有这些问题:dispatch无脑往下游转发,sharding规则非常僵硬,一个用户的push一定要打到某个节点,未做故障转移;当某节点异常满载时,dispatch还是会往这个节点打,导致丢消息或者是 push发送得慢。而且当节点满载时,有限的cpu还需要耗费在rpc解包、无法插入内存队列而丢弃之类的无用消耗上。

5.4 链路处理无优先级区分

运营人工发的 PUSH 和自动化 PUSH 都使用同一个下发链路,热点突发事件资讯多由运营人工发送,而自动化 PUSH 多发一些用户可能感兴趣的内容,其实它对于推送速度并没那么敏感;当有人工推送的热点突发内容时,自动化 PUSH 会和它一起争抢有限的链路资源。

另外,在链路总吞吐量一定的情况下,其实处理顺序可以调整,让链路资源有限保证人工推送的热点突发内容的发送;

5.5 技术栈不统一

之前 push 下发链路有 C++/Go 两种技术栈,技术栈不统一不利于代码复用,影响需求迭代效率。push下发链路本质上是一个高 io 型的流程,其实可以完全可以统一到 Golang 技术栈。

5.6 链路测试效率低

push 链路业务逻辑比较多,在日常密集业务需求迭代中,新功能我们可以在线上通过构造对应的功能 case 来进行冒烟测试,但是比较难评估是否影响了线上已有的业务逻辑。

之前缺乏有效的回归测试手段,由于担心影响线上业务指标,为了验证是否影响线上已有业务逻辑,我们大的修改都会开比较长的小流量实验验证,比如我们在做调度架构升级时,开了一个近两个月的小流量实验,测试效率比较低也会导致需求迭代效率比较低。

6、新Push架构优化1:消息通道自建

之前新闻 PUSH 依赖于平台侧的消息通道,业务侧主要负责 PUSH 调度,即业务侧决定触发和过滤,平台侧负责 PUSH 触达给用户终端。

由于 PUSH 是新闻增长护盘的重点方向,有较频繁的业务迭代,对底层消息通道我们有较多的业务需求,在业务迭代过程中我们发现平台侧需求 leadtime 比较长,无法满足业务侧迭代效率的要求;在经平台侧这边商量且同意后,我们完成新闻push消息通道的自研,直接对接厂商推送并搭建了长链接通道,实现了 push 全链路在业务侧的全闭环。

我们在自建 push 消息通道时,对原来的架构做了重写:

1)精简链路,模块整合,减少系统复杂度:去掉我们不关心的无用功能,将原链路15个模块,代码 68 万行整合为了6个模块,代码共8.6万行;通过代码精简能减少系统复杂度,有助于提升业务迭代效率;同时能避免模块之间的rpc通信开销,提升链路处理效率。

2)客户端/服务端交互接口整合,提升数据通信成功率:以前 PUSH 注册依赖于注册&绑定&上报三个接口请求,任何一次请求出错,push 注册就会失败;我们在新流程里将注册&绑定&上报需要的所有数据,都一起传给新接口,由服务端在一个接口里实现注册、绑定和上报;将注册成功率从90%提升到了99.9%。

3)与新闻技术技术架构保持统一:将原架构发现/rpc技术栈的基础组件升级为腾讯新闻自用的基础组件,尽量使用我们熟练使用的技术栈,以提升业务开发&运维效率。

4)优化了原来链路一些不合理的地方:对原来链路的限流机制、通道选择策略做了优化,增加了必要的功能,比如小流量实验环境的支持。

7、新Push架构优化2:统一技术栈

之前 push 链路有 C++/Golang 两种技术栈,除了 push 推荐服务外, 其它 C++链路模块全部使用 Golang 模块进行了重写,以提升业务迭代效率和链路稳定性。

8、新Push架构优化3:链路整合升级,提升效率

一个架构如果如果过度微服务化了,会带来各种问题:

  • 1)模块间耦合严重,影响研发效率:本来是一个模块应该完成的工作,硬拆成了2个模块,有改动需要都需要改两个模块,需要模块间联调测试,影响需求迭代效率。
  • 2)架构效率低:拆成微服务后,函数本地调用变成了RPC网络调用,需要增加大量的拆包、解包的操作,资源白白浪费在这些无用的内耗上了。

对于频繁迭代的地方,单独抽成单独的微服务是有助于提升迭代效率的;但是我们review历史push需求,都比较分散,没有集中到一个特定的地方,我们按照“一个需求尽量只用改一个模块”的原则,对原来的push链路的所有模块进行了整合升级。

具体的升级内容是:

  • a. 触发侧合并为了1个模块:将原来触发侧的5个模块合并为1个模块;
  • b. 调度侧合并为了1个模块:将原来调度侧的5个模块合并为了1个模块;
  • c. 将消息通道侧模块做了整合:如上所述,我们将push消息通道原来15个模块合并为了5个。

经过链路整合后:以前一个 PUSH 消息最多要经过 18 个模块,17次内部链路rpc转发;升级后,只用经过 3 个模块,只用经过 2 次 rpc 转发;这样就显著提升了链路效率;而且模块减少后,业务需要迭代无需开发多个模块,避免模块之间联调和测试,提升了业务迭代效率;同时,线上 case 排查时,无需做多模块的日志 join,提升了 case 排查效率。

9、新Push架构优化4:自建号码包服务,提升号码包获取速度

如上文所述:之前号码包的拉取慢是系统的主要瓶颈所在,而在我们这个场景比较简单,因此我们考虑自建号码包服务,针对于我们自己的需求来定制开发,以提升服务性能。我们的需求只有一个,就是对离线包进行分页,并提供服务接口返回指定页的数据。

1)画像中台圈选兴趣包,并按页切成若干个小文件,每个兴趣包一个文件夹,并上传到cos,兴趣包里带着数据版本号;

2)构建包管理服务,提供获取指定兴趣包指定页数据的能力;包管理服务定期从cos上check是否有更新的数据(比较本地数据版本和cos最新的数据版本),如果有,则拉取最新的数据更新本地数据;当接收到拉取指定包指定页数据的请求后,则定位到对应文件夹读取对应页文件数据并返回;

3)集群有个数据一致性哨兵,定期检查集群节点的数据版本,当发现集群数据版本不一致时,给集群所有节点发信号,强制让每个节点同步cos上的最新数据,让集群所有节点数据跟最新数据保持一致。

2

10、新Push架构优化5:在线过滤改成离线预处理,避免在线处理耗时

运营在发PUSH时会选择受众人群包,同时会指定系统、品牌等筛选项,之前的处理流程是先把人群包一股脑发到链路里,然后在下发链路里根据用户画像数据,对数据进行实时过滤。在线过滤增加了链路下发的耗时。

其实系统&品牌过滤完全可以前置到离线侧,我们将号码包按品牌和系统维度进行了拆分,比如“社会”包按 android/ios、huawei/oppo/vivo/honor/xiaomi,拆成了13个包,当运营选择指定的筛选项时,直接拉取对应的号码包,这样就避免了在线过滤的耗时,减少了下发的延时。

11、新Push架构优化6:将单IO操作自动聚合成批量操作

push下发链路有大量io操作,比如获取用户维度的多路数据(比如用户系统、品牌、下发&曝光&点击历史等),获取文章维度的多路数据(文章正排数据等)。链路其实主要耗时还是在io部分,如果能提升io吞吐量,就能提升PUSH链路的吞吐量,减少下发延时;io操作批处理肯定能提升吞吐量。

但是在具体业务流程中,不同push类型、不用品牌用户,处理逻辑会有不同,因为每个push的处理流程可能都不一样,无法直接批处理。所以之前调度主链路流程是从队列里按单个消费进行处理的。

为了提升链路吞吐量,我们对每一类io操作做了一个类,对外暴露一个单个io请求接口,外部调用该接口后,将请求压入一个异步队列,同时开始等待结果的返回;这样该类io请求都会在该异步队列里进行了汇聚。

下层会开若干个处理协程,批量从异步队列消费出若干请求任务,拼成批量的io请求,然后拿到批量io结果,按序向上层返回io结果;

这样对上层而言,看到的还是单个的同步io接口,上层业务逻辑开发流程无需做改造,底层其实已经自动做了io的批量聚合,显著提升了链路吞吐量。

12、新Push架构优化7:优先推送热点突发内容,优先保证高价值用户及时性体验

在链路吞吐量一定的情况下,一个推送任务小到几百万,大到一两亿的发送量,都需要处理时间。这时候先处理比后处理的时延要少。

其实可以考虑对链路发送进行调度:

  • 1)链路优先保障热点突发PUSH的发送,我们建立了任务优先级队列,当有热点突发PUSH在发送时,其它PUSH延迟发送;
  • 2)同一个PUSH任务,对用户推送顺序也做了排序:活跃度高、历史push点击率高、预估商业化价值高、对push时延敏感的用户优先发送。

通过优先级调度,最大程度保障了热点突发内容和高价值用户的推送及时性的体感。

13、新Push架构优化8:增加自动故障恢复能力

为了提升链路吞吐量,调度节点进程通过 LRU cache 缓存了大量数据,所以在推送消息处理的 sharding 方式上采用了按设备号一致性哈希。

很多时候某个节点异常时,会出现慢而不死的情况:处理能力陡降,但是节点存活正常。北极星未能把它摘掉,相当一部分设备会打到该节点,即使该节点已经满载了,之前架构为了避免缓存失效而导致处理耗时增加,还是会一致性哈希将流量打往该节点,导致这部分用户处理耗时异常增加,甚至发送失败。

新架构对于推送任务sharding做了优化:在一致性哈希的基础上,每个节点计算出4个固定的backup;当某节点的失败率或处理耗时超过一定阈值时,将该节点的流量均匀低分给他的backup。通过这种方式就支持单节点异常时的自动故障恢复。

14、新Push架构优化9:构建push链路自动化测试能力

构建了接口自动化回归测试流程:

  • 1)case覆盖push链路的核心逻辑;
  • 2)合并master时自动触发回归测试流程的执行。

构建了自动化diff测试流程:

diff流程大体思路都类似,通过录制线上流量的真实请求和返回结果,在测试环境进行回放,观察同一请求下,返回结果是否会有差别;如果无差别,说明测试环境跟线上一样,上线不会引起线上数据异常;如果有差别,就需要分析这些差别是否是符合预期的。

diff测试基本能回归到线上所有业务逻辑分支,能弥补回归测试覆盖度有限的问题。

主要挑战:

push依赖的数据变化比较快,导致在同一时间,同一请求的返回结果会不同;比如push为了避免重复下发同一篇文章,会依赖于下发历史数据,线上录制了刚下发的某篇文章,在测试环境去回放肯定就不能下发了,因为线上刚把这篇文章写入到下发历史里,导致回放请求时返回结果是不能下发了,这样自然就产生了diff。

解决方案:

在流量录制时,除了录制请求之外,同时录制各个依赖数据,在回放时,依赖数据以依赖数据为准,通过这种方案就避免了依赖数据易变而引入diff的问题。

15、架构升级后的系统表现

1)push运营成本显著降低:通过持续的 push 架构优化,新闻 push 总运营成本下降70%;

2)PUSH链路性能(吞吐量)显著提升:通过持续的 push 架构优化,显著提升了 push 链路的性能,push推送量(出口)峰值吞吐量提升了3.5倍;

3)热点突发(全国/快速)PUSH全链路耗时下降明显:

  • a. 热点突发(全国/快速)PUSH内部链路耗时P90下降了90%;
  • b. 内部链路耗时指的是从push审核通过到推送给厂商的时间,即我们内部链路总的耗时时长;
  • c. 热点突发(全国/快速)PUSH全链路耗时(包括内部链路耗时和厂商链路耗时)下降了90%
  • d. 全链路耗时指的是从push审核通过到用户收到PUSH时间,即包括内部链路和厂商链路总的耗时时长.

我们完成一些架构升级后,还是评测团队对了评测,腾讯新闻的PUSH已经领先于竞品1~4分钟了。

4)提升了PUSH点击效果:

push推送速度提升后,push点击数据也能看到明显受益,热点突发PUSH点击pv提升了10%,push大盘点击UV也能看到显著的正向收益;

线上收不到PUSH的用户客诉也减少到25年H1 0 例,提升了用户产品体验。

5)稳定性良好:push链路主要重构完成后,PUSH链路稳定性&质量明显提升,2025.02以后 0 故障。

16、参考资料

[1] 极光推送系统大规模高并发架构的技术实践分享

[2] 魅族2500万长连接的实时消息推送架构的技术实践分享

[3] 专访魅族架构师:海量长连接的实时消息推送系统的心得体会

[4] 一个基于长连接的安全可扩展的订阅/推送服务实现思路

[5] 实践分享:如何构建一套高可用的移动端消息推送系统?

[6] Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)

[7] 腾讯信鸽技术分享:百亿级实时消息推送的实战经验

[8] 百万在线的美拍直播弹幕系统的实时推送技术实践之路

[9] 京东京麦商家开放平台的消息推送架构演进之路

[10] 技术干货:从零开始,教你设计一个百万级的消息推送系统

[11] 长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践

[12] 喜马拉雅亿级用户量的离线消息推送系统架构设计实践

[13] 直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践

[14] 消息推送技术干货:美团实时消息推送服务的技术演进之路

[15] 揭秘vivo百亿级厂商消息推送平台的高可用技术实践

[16] 得物从零构建亿级消息推送系统的送达稳定性监控体系技术实践

[17] B站千万级长连接实时消息系统的架构设计与实践

[18] 转转千万级用户量消息推送系统的架构演进之路

[19] 企业级实时消息推送系统的架构设计,一文即懂!

技术交流:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

(本文已同步发布于:http://www.52im.net/thread-4883-1-1.html

posted @ 2025-12-08 19:12 Jack Jiang 阅读(39) | 评论 (0)编辑 收藏

本文由自字节跳动技术肖新蔚、赵彦奇分享,有修订和重新排版。

1、引言

本文要分享的是字节跳动团队针对火山HTTPDNS Cache2.0通过自研网段库与动态划分算法,将缓存粒度从“城市-运营商”细化为“网段”,解决了传统方案的城市级调度污染问题。配合缓存分级、预取等优化,在提升调度精准度的同时保证了高命中率,最终实现了服务端调度准确性提升和客户端性能优化。

cover-opti

技术交流:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

(本文已同步发布于:http://www.52im.net/thread-4876-1-1.html

2、系列文章

移动端弱网优化专题(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端弱网优化专题(二):史上最全移动弱网络优化方法总结

移动端弱网优化专题(三):现代移动端网络短连接的优化手段总结

移动端弱网优化专题(四):百度APP网络深度优化实践(DNS优化篇)

移动端弱网优化专题(五):百度APP网络深度优化实践(网络连接优化篇)

移动端弱网优化专题(六):百度APP网络深度优化实践(移动弱网优化篇)

移动端弱网优化专题(七):爱奇艺APP网络优化实践(网络请求成功率优化篇)

移动端弱网优化专题(八):美团点评的网络优化实践(大幅提升连接成功率、速度等)

移动端弱网优化专题(九):淘宝移动端统一网络库的架构演进和弱网优化实践

移动端弱网优化专题(十):爱奇艺APP跨国弱网通信的优化实践

移动端弱网优化专题(十一):美图APP的移动端DNS优化实践

移动端弱网优化专题(十二):得物自研移动端弱网诊断工具的技术实践

移动端弱网优化专题(十三):得物移动端常见白屏问题优化(网络优化篇)

移动端弱网优化专题(十四):携程APP移动网络优化实践(弱网识别篇)

移动端弱网优化专题(十五):字节跳动移动端网络HttpDNS优化实践》(☜ 本文

3、技术背景

在字节跳动的业务生态中,HTTPDNS 承担着为抖音、今日头条、西瓜视频等核心应用提供域名解析服务的重任。但目前我们所采用的业界主流缓存机制(火山Cache1.0),却存在着调度不准的问题。

这些问题主要是:

  • 1)业界主流缓存机制的问题;
  • 2)缓存粒度:城市-运营商;
  • 3)致命缺陷:当自身IP库与权威DNS服务器不同,易发生调度不准,可能影响用户体验。

4、主流HttpDNS调度修正机制的局限性

针对 HTTPDNS 调度不准风险,业界主流处置流程采用 “发现-定位-修复” 三步闭环机制.

具体如下:

  • 1)发现:通过监控告警、业务异常反馈等方式,识别存在调度偏差的解析场景;
  • 2)定位:结合访问日志、链路追踪数据等,定位调度不准的具体域名、源IP段和目标 IP 段;
  • 3)修复:通过技术手段修正解析结果。

针对上述第 3)点,核心修复方式包含以下两类(均存在显著局限性):

  • 1)地址库升级:基于外部供应商数据聚合构建的 IP 地址库,即使实时更新,仍难与外部 CDN 厂商的映射保持一致;
  • 2)临时劫持:手动配置解析劫持规则修正解析结果,不仅操作流程繁琐、耗时长,且需人工维护大量静态配置;若规则未得到及时维护,易引发解析结果异常。 
1

5、主流厂商的HttpDNS缓存粒度技术方案

缓存粒度设计直接影响 DNS 解析精准度,主流厂商的方案存在明显差异:

2

6、HttpDNS的缓存键精细化重构

我们综合考量调度精准度、工程复杂度以及成本,决定将缓存粒度由“城市+运营商”细化为“网段”。

6.1 传统方案(国内某厂商/火山Cache1.0)

3

  • 1)缓存粒度:城市+运营商;
  • 2)污染范围:整个城市运营商;
  • 3)调度准确性:低。

6.2 Cache2.0方案

4
  • 1)缓存粒度:网段;
  • 2)污染范围:单个网段;
  • 3)调度准确性:高。

6.3 网段自适应划分算法

背景:外部 CDN 厂商的调度结果会随网络拓扑和调度策略持续变化,而静态网段库划分方式固定,难以实时跟踪调度结果变化。

为解决这一问题,网段库动态划分算法通过“数据输入—一致性校验—网段调整—结果输出”的闭环流程,实现了网段库的自适应动态划分。

具体流程如下。

1)数据输入:

* 收集客户端IP—CDN IP映射数据:

  • a)数据来源:主动拨测结果;HTTPDNS 递归节点日志;
  • b)数据范围:主流CDN厂商的解析结果。

* 网段归属判断:

  • a)若相邻客户端IP的CDN IP 归属同一运营商,则该组CIP可合并为连续网段;
  • b)将合并后的连续网段输出,作为探测网段数据集。

2)一致性校验:

  • a)将探测网段数据集与存量CIDRDB网段库进行逐网段对比,检查 “映射一致性”;
  • b)若存在映射不一致,则触发网段调整流程。

3)网段调整:

  • a)合并:探测数据集的网段比现有库粗,合并为大网段;
  • b)拆分:探测数据集的网段比现有库细,拆分为小网段。

4)结果输出:

  • a)生成优化后的新CIDRDB网段库;
  • b)替换存量网段库,实现动态更新。

5)持续迭代:

  • a)重复上述流程,实现网段库的自适应动态划分。
5

7、HttpDNS的缓存策略优化

为解决缓存粒度细化可能导致的命中率下降问题,Cache2.0 引入了四重优化策略,最终实现了如下收益:

缓存命中率提高了15%,缓存量、CPU 使用和出网流量降低了约70%。

1)两级一致性哈希分流:

火山 HTTPDNS 的流量转发以一致性哈希思想为核心,将用户请求链路(用户→LB→缓存层→递归层)拆分为两级哈希调度:

  • a)一级调度(LB→缓存层):以“源 IP + 域名”为哈希键。使用LB的一致性哈希策略,将同一用户对同一域名的请求统一路由至固定的 HTTPDNS 节点,避免传统轮询导致的请求分散;
  • b)二级调度(缓存层→递归层):以“域名 + 网段” 为哈希键。以 “域名 + 客户端网段” 作为哈希键,与缓存粒度完全对齐,确保某一“域名 + 网段”对应的查询请求均定向到唯一的递归层节点。

两级哈希协同调度,解决了缓存的碎片化问题,同时单一节点故障影响范围极小。

6

 


 

2)缓存分级管理:

在 HTTPDNS 场景中,不同域名对解析精度的需求不同。高优先级域名(如API 调用、直播 / 点播流媒体分发)对解析精准性要求高,跨网可能导致访问延迟增加;而低精度需求域名(如302域名)采用过细缓存会浪费存储资源,频繁回源也会增加权威 DNS 压力。

为实现缓存资源的精细化分配,火山 HTTPDNS 将缓存体系划分为“网段缓存、城市 - 运营商缓存、全局缓存” 三级,各级缓存适配不同应用场景。

具体是:

1)网段缓存:作为最高精度层级,聚焦高优先级业务场景 :一方面适配高优域名(如抖音 API 调用、图片分发、点播 / 直播流媒体传输等对精准性敏感的域名),另一方面服务重点集群(如 ToB 企业 HTTPDNS 服务、ToB 专属公共 DNS 服务),通过网段级细粒度缓存确保解析结果与用户实际网络链路高度匹配,降低访问延迟;

2)城市 - 运营商缓存:定位中等精度层级,适配普通域名场景:针对调度精准度要求较低的域名,以 “城市 + 运营商” 为缓存单元,平衡缓存命中率与存储开销;

3)全局缓存:作为基础精度层级,专门适配非智能解析域名:针对不支持 CDN 动态调度、解析结果无地域 / 运营商差异的域名(如静态官网、通用工具类服务域名),采用全局统一缓存策略,所有用户查询共享同一缓存结果,最大化提升缓存命中率,降低回源请求压力。

7

3)缓存更新分级策略:

在 HTTPDNS 系统中,统一的主动刷新策略虽然能保证缓存命中率,但存在明显问题:对不需要精细调度的域名浪费了存储资源,增加了下游压力。

基于以上问题,火山 HTTPDNS引入 “主动刷新 + 被动刷新”分级策略,以域名优先级和业务需求为依据,将缓存更新机制分为两类。

具体是:

  • a)后台线程主动刷新机制:针对高优域名(白名单),保留后台线程主动刷新,确保缓存持续有效、用户请求直接命中最新数据;
  • b)用户请求被动刷新机制:针对普通域名或非智能解析域名,由请求触发缓存更新,按需刷新,无需常驻后台刷新线程,降低资源消耗。

通过这种分级更新策略,高优先级域名仍能保证低延迟和高命中率,同时普通域名的刷新开销显著降低。

4)缓存预取机制:

依托 “缓存空间局部性原理”,火山 HTTPDNS 设计了缓存预取机制。当某条缓存请求(如 A 网段域名解析)触发更新时,系统不仅刷新目标网段缓存,还会同步更新与其具有 “亲缘关系” 的网段缓存(“亲缘关系”指地理相邻、同运营商节点覆盖的网段)。这种 “单次请求触发批量预取” 的设计能够提前将关联网段缓存置于准备状态,提升后续请求的命中率。

以抖音直播域名的实际访问场景为例,预取机制的运作过程如下:

  • a)本网段更新:当用户 A(IP 归属北京联通 10.0.1.0/24 网段)发起直播域名解析请求时,系统首先刷新其所属的 10.0.1.0/24 网段缓存;
  • b)预取更新:系统同时刷新与 10.0.1.0/24 网段具有亲缘关系的网段缓存,例如北京联通下的相邻网段(10.0.2.0/24、10.0.3.0/24),确保这些网段缓存也处于准备状态。

随后,当用户 B(10.0.2.0/24)或用户 C(10.0.10.0/24)发起相同直播域名的解析请求时,由于对应网段缓存已提前预取,无需等待回源即可直接命中缓存,显著降低访问延迟。

8、HttpDNS优化后的实际效果

8

服务端调度精准度提高:借助网段级缓存,用户获取的 IP 地址更加精准。按服务端日志数据口径,调度不准比例从万分之六下降至万分之二,降幅 60%,有效缓解了传统粗粒度缓存导致的“城市级缓存污染”问题。

客户端性能优化:

  • 1)成功率:核心 feed 接口,在弱网+非连接复用场景下提升 1.15%;
  • 2)耗时:非连接复用场景耗时减少14ms。
9

用户体验提升:

  • 1)性能指标:首刷及启动耗时下降;
  • 2)用户指标:用户行为指标(send 与 click)正向,用户活跃度提升。

本方案通过服务端精准调度 → 客户端性能优化 → 用户体验提升,实现了全链路效能提升。

9、持续演进方向——共享缓存

目前,各机房的负载均衡策略与缓存策略未能完全对齐(部分采用随机转发,部分虽然使用一致性哈希但粒度不一致),导致同一数据在多个实例中被重复缓存,资源利用率偏低,缓存命中率也有待提升。

未来,我们计划构建一个分层共享的高可用缓存体系:

1)在同一机房内,实例通过一致性哈希协同分工,每台实例既是分片缓存,也能代理转发请求,从而减少重复存储并提升命中率;

2)在跨机房层面,按区域部署二级缓存节点,作为容量更大、延迟更低的共享中心,承接一级未命中的请求,降低跨区域访问和上游压力。与此同时,引入热点数据副本、请求合并和故障转移等机制,保证高并发和异常情况下的稳定性与可用性。

通过这一演进,整体架构将逐步升级为层次化、分布式且具备高可用能力的缓存网络,为业务的持续扩展提供坚实支撑。

10、参考资料

[1] TCP/IP详解 卷1:协议 - 第14章 DNS:域名系统

[2] 网络编程懒人入门(七):深入浅出,全面理解HTTP协议

[3] 网络编程懒人入门(十二):快速读懂Http/3协议,一篇就够!

[4] 从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路

[5] 脑残式网络编程入门(三):HTTP协议必知必会的一些知识

[6] 全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等

[7] 通俗易懂,理解移动网络的“弱”和“慢”

[8] 现代移动端网络短连接的优化手段总结

[9] 百度APP网络深度优化实践(DNS优化篇)

[10] 爱奇艺APP网络优化实践(网络请求成功率优化篇)

[11] 美团点评的网络优化实践(大幅提升连接成功率、速度等)

[12] 淘宝移动端统一网络库的架构演进和弱网优化实践

[13] 爱奇艺APP跨国弱网通信的优化实践

[14] 得物自研移动端弱网诊断工具的技术实践

[15] 携程APP移动网络优化实践(弱网识别篇)

(本文同步发布于:http://www.52im.net/thread-4876-1-1.html

posted @ 2025-11-25 10:45 Jack Jiang 阅读(43) | 评论 (0)编辑 收藏

Jack Jiang的 Mail: jb2011@163.com, 联系QQ: 413980957, 微信: hellojackjiang