默认

本文目录

打赏 发表评论 0
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
微信读书十周年,后台架构的技术演进和实践总结
阅读(1376) | 评论(0 收藏1 淘帖1 1
微信扫一扫关注!

本文由腾讯技术团队罗国佳分享,原题“微信读书后台架构演进之路”,即时通讯网有修订和重新排版。


1、前言


今年是微信读书上线10周年,后台技术架构也伴随着微信读书的成长经历了多次迭代与升级。每一次的组件升级与架构突破,在一个运行了10年的系统上落地都不是一件容易的事情,需要破釜沉舟的决心与胆大心细的业务联动。

微信读书经过了多年的发展,赢得了良好的用户口碑,后台系统的服务质量直接影响着用户的体验。团队多年来始终保持着“小而美”的基因,快速试错与迭代成为常态。后台团队在日常业务开发的同时,需要主动寻求更多架构上的突破,提升后台服务的可用性、扩展性,以不断适应业务与团队的变化。

微信读书十周年,后台架构的技术演进和实践总结_cover-opti.png

2、整体架构设计


微信读书是独立于微信的App,且由于历史原因,开发及运维环境均存在一定的差异与隔离。因此,微信读书的后台服务实现了从接入层到存储层的一整套完整架构。

微信读书十周年,后台架构的技术演进和实践总结_1.png

架构上分解为典型的接入层、逻辑层和存储层:

1)接入层:按业务划分为多个CGI服务,实现了资源隔离。在CGI层面还实现了如路由、频控、接入层缓存、长连接等。

2)逻辑层:采用WRMesh框架构建了多个微服务,这些微服务按业务场景进行划分,实现了不同模块间的解耦。框架也提供了如RPC、路由发现、过载保护、限流频控、监控上报等能力。

3)存储层:主要采用PaxosStore存储用户数据,分为K-V和K-Table两种类型,具备高可用、强一致的特性,针对String和Table两种类型定制了缓存中间件,以适配某些业务场景下对访问存储的性能要求。BookStore提供书籍的存储服务,满足读书场景下对书籍的拆章、修改、下载等需要。此外,也不同程度地使用了腾讯云的PaaS存储服务,以灵活满足更多场景需要。

具体的业务逻辑不再赘述,下面简单介绍下微信读书近几年在后台架构上的一些演进。

3、异构服务间调用:RPC框架


微信读书后台微服务源于Hikit框架,采用C++开发。该框架诞生于广研、QQ邮箱年代,在性能、容灾、运维、监控层面都经受了线上的考验,在微信读书上线初期作为主要框架,支撑了后台服务长达数年。

随着微信读书的发展,越来越多异构的系统发展起来。例如推荐算法系统是独立部署在TKE上的容器服务,采用GO语言开发,好处是历史负担少,运维更加方便、开发更加便捷。

两套系统同时存在带来的问题是如何做好服务治理,推荐系统需要频繁调用后台基础模块获取用户数据,必须要有一套完善的路由管理、容灾机制,且考虑到是异构服务,开发语言也不相同,如果为每种语言都定制开发一套服务治理框架,代价会非常高。

在这个阶段,我们开发了WRMesh框架,采用Sidecar+Business的方式解决这个问题。

微信读书十周年,后台架构的技术演进和实践总结_2.png

Sidecar专注于处理网络层的逻辑,和Business业务层分开为两个进程,由WRMesh脚手架生成代码,上层业务无需感知。

Sidecar集成了Hikit框架中用于服务治理的核心逻辑:通过UnixSocket与Business进行通信,代理Business的所有网络读写。当Business进程中需要发起网络请求时,由WRMesh生成的Client代码会自动识别当前是否在mesh环境中,并转发请求给Sidecar,由Sidecar完成接下来的网络处理。

因此:Business进程可以由任意语言任意框架开发,只要遵循Sidecar的通信协议,只需要薄薄的一层网络协议转换即可接入到Hikit的服务治理框架中。

另外:对于某些有特殊路由逻辑的Client,如KV访问、Batch请求等,代理转发并不能满足要求,因此Sidecar还提供了插件能力集成这些Client逻辑,最大限度为异构Business业务提供原生C++的能力。

随着WXG容器平台P6N的建设越来越完善,许多微信的能力也是基于P6N提供,我们也在思考如何逐步迁移到P6N。由于微信读书后台运维目前依赖于企微团队,有独立于P6N的一套运维体系,我们负责业务和架构开发。

如果要一刀切把所有后台服务迁移至P6N,将会面临几个问题:

1)框架代码需要重新适配,开发环境和现网环境都有巨大的改造成本。

2)迁移不是一蹴而就,后台上百个服务在迁移过程中,会存在新旧服务互调的问题,由于运维环境不互通,微服务之间无法完成服务治理,这种互相调用最终只能通过Proxy来转发,不仅增加了网络的失败率,时延增加,最关键的是这个过程会让容灾体系大打折扣。

3)存储模块的迁移成本和风险巨大,如果不迁移存储模块只迁移了逻辑模块,那势必又会存在2中的问题,这个过程很难收尾。

考虑到人力成本及投入性价比,我们最终采用了折衷的方案:

  • 1)一方面:我们保留了依赖于企微的运维环境,保障绝大多数现成服务的稳定运行。
  • 2)另一面:对于微信P6N中的服务,我们搭建了比较完善的Proxy层,例如Svrkit代理、WQueue代理等,两套架构可以方便进行互通,最大限度的在原有基础上接入微信的新能力。

目前,微信读书已顺利接入如WQueue、FKVOL、SimOL、TFCC等众多微信的能力。

4、书籍数据中台的演进


4.1技术背景


书籍是微信读书的内容根基,书籍数量的多少、书籍质量的好坏,很大程度上决定了用户是否选择微信读书作为阅读App。

过去:我们依托阅文集团提供电子书资源,免去了书籍上架前繁琐的处理流程,包括排版、审校、元信息管理、更新管理等,后台服务只需要对接阅文API即可方便获取书籍数据,我们只需要关注书籍在平台的存储管理和分发流转即可。

近几年:电子书行业的大环境发生变化,一方面,用户对书籍品类多样性、内容质量有更高的诉求,另一方面,平台对成本、版权等行业因素也更为敏感。因此,我们也在积极探索自签版权,甚至是自出品的模式,尝试走更多不一样的道路。从后台角度而言,从过去单一依赖阅文集团API的模式,慢慢转为开放更多的书籍管理接口,形成书籍数据中台模式,为上层运营同学搭建内容管理平台,让更多人可以方便参与到电子书的制作、排版、上下架、运营管理当中。

以EPUB为例,从内容产出到上架到微信读书,大致经历以下阶段:

1)排版审校:这个阶段多为人工或者部分机器自动化介入。

2)上架预处理:这个阶段需要创建书籍信息,配置各种运营策略,当这本书是重排版上架时,内容发生改变,由于现网已经存在用户的划线笔记、进度等数据,需要有完善指标评估是否适合覆盖上架,当上架时,需要对用户数据进行修复,避免发生错位情况,严重影响用户体验。

3)EPUB解析:当书籍上架后,由于EPUB是单一文件,不适合解析和管理分发,因此后台会把源文件解析成自有格式,包括EPUB拆章、图文分离、样式分离、按章生成离线包等等。

4)生成BookInfo和BookData并落盘:EPUB文件经过解析后,BookInfo和BookData会存储到自建的StoreSvr服务上,StoreSvr针对书籍存储、下载等场景进行了很多优化,具备高可用、低时延的特点,提供了书籍信息获取、按章下载等核心接口。

4.2建设数据中台


回到最初的目标,我们希望把更多的书籍管理能力开放出来,对上层屏蔽电子书底层的后台逻辑,让运营同学可以更专注于书籍的管理。

因此,我们构建了如下书籍数据中台:
微信读书十周年,后台架构的技术演进和实践总结_3.png

后台服务拆分开StoreAPI和StoreSvr:

  • 1)StoreAPI:提供书籍管理的接口,由运营同学搭建的内容平台与StoreAPI交互,完成书籍的管理工作;
  • 2)StoreSvr:一方面接受StoreAPI的请求,更新书籍数据,另一方面为现网用户提供高可用的服务。

StoreAPI提供了如下接口能力:

  • 1)书籍id分配、上下架;
  • 2)书籍信息创建、修改;
  • 3)书籍内容修改、连载更新、订阅推送;
  • 4)运营策略管理。

此外:如上所述,划线位置和阅读进度等核心UGC数据由于是按文件偏移记录,当书籍文件替换后,这些数据会发生错位,如果不能及时修复,将对用户体验造成巨大影响。尤其在一些热门书籍里,单本书里与位置相关的UGC数据往往能达到亿级别,由于文件替换后位置的偏移具有随机性,并不能采用简单的映射方式解决,在过去,我们开发了专门的修复服务来完成这个事情,针对每一个UGC内容,采用全文模糊查找的方式重新计算新的偏移,并更新的UGC正排、书籍倒排等多个存储中。

但随着用户数据越来越多,书籍替换频率越来越频繁,修复不及时或者失败的问题逐渐暴露出来:

  • 1)修复量大导致修复不及时。过去的修复服务虽然是多机部署,但处理单本书仍只是集中在一台机器上,单机性能有限;
  • 2)修复任务缺乏落盘管理,修复服务一旦重启,任务丢失。

针对上面的问题:我们重新设计了修复服务,目标是最大限度缩短修复时间,并且让整个过程是可靠的。

为此,我们先首手考虑业务流程,我们发现在书籍上架前,运营同学本来就需要依赖UGC的修复情况做前置判断是否覆盖上架,这个过程中虽然是对UGC抽样评估,如果能对这个修复映射结果进行缓存,在正式替换文件后,也能一定程度提升修复速度。

在核心修复流程中,我们进行了较大的重构,把单本书的修复任务拆解成多个子任务,存储在Chubby上,多机器抢锁共同消费这些任务,由于任务有落盘,在服务上线重启过程中,也能马上恢复。修复过程涉及大量的KV写入,并发太高时容易命中单key的限频或者版本冲突,我们为此开发了针对K-Str和K-Table的写入中间件,可以在内存中聚合一批请求进行批量合并写入,缓解KV层面的失败。

微信读书十周年,后台架构的技术演进和实践总结_4.png

目前,微信读书已通过内容平台完成了多家版权方自签,并在探索自出品等内容创作新形式。

5、账号系统的高可用性重构


账号是微信读书后台系统的基石,承担了登录、会话密钥生成与派发、用户资料管理等核心功能,所有的用户请求都需经过账号系统进行鉴权验证用户身份,但凡有一点系统抖动都会影响到整个App的正常使用,严重者还会导致账号被踢出无法再次登录。

账号系统的架构在微信读书诞生之初便一直沿用,同一个号段的账号服务AccountSvr和MySQL部署在同一台机器上,备机采用主从同步的方式获取数据,当主机不可用时,备机承担了所有读请求。

在某些场景下,为了能使访问备机时也具备一定的写入能力,曾经魔改过主备逻辑,但一切都显得治标不治本,且引入了更复杂的系统特性,整个架构略显混乱。在机器裁撤、数据扩容过程中,曾造成过几次严重故障,导致App不可用,严重影响用户体验。究其原因,是因为当时基础设施还不完善,缺少高性能高可靠的强一致存储,MySQL也是手动搭建的,运维成本和风险都非常高。

为了彻底解决这个历史包袱,我们在2024下定决心对其进行重构。重构就意味着要抛弃现有MySQL这套臃肿的存储方案,把数据迁移到新的存储组件上。

这里涉及到的挑战点如下:

  • 1)账号鉴权服务访问量巨大,迁移过程须尽量不增加系统负担,且必须是在不停机的情况下进行;
  • 2)迁移过程中一旦有数据丢失或者错误,会导致用户资料受损,用户登录态丢失,App无法使用;
  • 3)账号系统还涉及用户id分配和回收逻辑,在切换存储时如何保证数据的一致性,不重复分配号码。

背水一战,没有退路可言。在经历了多次论证后,我们决定采用Paxosmemkv作为新的存储组件,全内存、多副本、强一致的特性,很适合作为账号系统的底层存储。

同时,我们为整个迁移过程制定了周密的方案,把每一步进行了分解,且要求每个环节可灰度可回退,同时要做好数据的一致性检查。

在完成数据迁移后,我们还需要对AccountSvr进行重构,抛弃按号段的账号分配、路由、缓存逻辑,以全新的视角设计更简洁的架构。

6、内容召回系统的架构设计


以往微信读书的搜索仅限于基于书名、作者等维度的文本召回,通过自建的全内存索引服务实现书籍的检索。全文检索则基于ES搭建,采用规则分段的方式建立索引,能满足读书大部分场景的需要。

在大语言模型迅速发展的近两年,微信读书作为一个庞大的内容知识库,具有大量的书籍原文资源。同时,用户在微信读书也留下了大量的文字内容,如书评、想法等,这些内容构成了AI问书的内容基石,也是AI问书区别于其它问答工具的核心优势。

基于微信读书构建RAG召回系统,核心挑战如下:

1)基于书籍原文构建全文检索,为了达到最好的效果,往往需要支持按语义进行段落切分,在此基础上构建embedding进行语义召回。微信读书拥有百万级书籍原文数据,此外,对于用户导入书,更是达到亿级别规模。现有架构无论从成本还是耗时上都无法解决。

2)为了支持更多维度的召回,需要对UGC内容进行召回,部分UGC内容属于私密信息,并不向全网公开,只需要满足用户个人检索即可。此时如果用常规的检索系统构建常驻索引,访问率太低,成本难以收敛。

为此,我们针对微信读书不同的RAG使用场景,设计了如下召回架构:
微信读书十周年,后台架构的技术演进和实践总结_5.png

我们把数据划分成两类:全局公开可搜以及用户个人可搜。

1)对于全局公开可搜索的数据:如库内电子书的全文、书籍大纲、书评、人工知识库等,我们构建了一套入库流程,能对源信息进行语义分段、生成正排倒排,语义分段基于开源的chunk模型进行微调,正排基于fkv,倒排则基于ES构建,ES提供了DiskANN方案,通过设置合理的缓存和分片,能在存储成本和召回效率之间取得不错的平衡。对于 App 内主搜等低时延场景,为了满足多种定制化检索需求,我们自建了基于内存索引的Searchsvr服务,支持索引落盘,可以在毫秒级返回电子书搜索结果。

2)对于用户个人数据:如导入书全文、个人想法等,特点是数据量大但使用频率不高,不需要针对全网用户进行检索,如果采用上述方案,会带来成本灾难,性价比极低。为此,我们按用户及物料的维度,基于USearch、Xapian等方案构建了向量及文本索引,这些组件的优势在于可以把单个索引存储成文件的形式,便于落盘,配合一些量化的方法,可以把大大压缩索引大小。在构建索引阶段,按用户+类型构建出不同的索引,并存储在低成本的COS上,当用户需要检索召回时,采用读时加载的方式实时进行召回,结合CFS进行预热可以大大提升检索速度。当检索完成后,定时淘汰策略会把长期不用的索引从CFS中清理,降低存储成本。

7、写在最后


虽然微信读书已经发展了十个年头,但我们的脚步从未停止。

在日常业务开发之余,我们也从未停止思考如何让系统能走得更远、更稳健,抓住每一个可能的优化点,随时做好准备,迎接下一个精彩的十年。

8、相关资料


[1] 腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面
[2] 快速理解高性能HTTP服务端的负载均衡技术原理
[3] 子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践
[4] 知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路
[5] 新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践
[6] 阿里技术分享:深度揭秘阿里数据库技术方案的10年变迁史
[7] 阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路
[8] 达达O2O后台架构演进实践:从0到4000高并发请求背后的努力
[9] 优秀后端架构师必会知识:史上最全MySQL大表优化方案总结
[10] 小米技术分享:解密小米抢购系统千万高并发架构的演进和实践
[11] 一篇读懂分布式架构下的负载均衡技术:分类、原理、算法、常见方案等
[12] 通俗易懂:如何设计能支撑百万并发的数据库架构?
[13] 多维度对比5款主流分布式MQ消息队列,妈妈再也不担心我的技术选型了
[14] 从新手到架构师,一篇就够:从100到1000万高并发的架构演进之路
[15] 美团技术分享:深度解密美团的分布式ID生成算法
[16] 12306抢票带来的启示:看我如何用Go实现百万QPS的秒杀系统(含源码)

9、微信团队的其它精华文章


微信后台基于时间序的海量数据冷热分级架构设计实践
微信团队原创分享:Android版微信的臃肿之困与模块化实践之路
微信后台团队:微信后台异步消息队列的优化升级实践分享
微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案
一份微信后台技术架构的总结性笔记
社交软件红包技术解密(十三):微信团队首次揭秘微信红包算法,为何你抢到的是0.01元
微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
IM“扫一扫”功能很好做?看看微信“扫一扫识物”的完整技术实现
微信团队分享:微信支付代码重构带来的移动端软件架构上的思考
IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总
微信团队分享:微信直播聊天室单房间1500万在线的消息架构演进之路
企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等
IM全文检索技术专题(四):微信iOS端的最新全文检索技术优化实践
微信团队分享:微信后台在海量并发请求下是如何做到不崩溃的
微信Windows端IM消息数据库的优化实践:查询慢、体积大、文件损坏等
微信技术分享:揭秘微信后台安全特征数据仓库的架构设计
企业微信针对百万级组织架构的客户端性能优化实践
揭秘企业微信是如何支持超大规模IM组织架构的——技术解读四维关系链
微信团队分享:详解iOS版微信视频号直播中因帧率异常导致的功耗问题
微信团队分享:微信后端海量数据查询从1000ms降到100ms的技术实践
大型IM工程重构实践:企业微信Android端的重构之路
IM技术干货:假如你来设计微信的群聊,你该怎么设计?
微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗
微信后团队分享:微信后台基于Ray的分布式AI计算技术实践
一年撸完百万行代码,企业微信的全新鸿蒙NEXT客户端架构演进之路

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:微信纯血鸿蒙版正式发布,295天走完微信14年技术之路!

本帖已收录至以下技术专辑

推荐方案
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部