【Java】设计一个支持10W QPS的评论中台,你会怎么设计?

一、内容分析

在B站,UP主每天都会发布海量的视频、动态、专栏等内容,随之而来的是弹幕和评论区的各种讨论。

播放器中直接滚动播放的弹幕,如同调味剂,重在提升视频观看体验;

而点进评论区,相对而言评论文本更长,内容的观点、形式都更丰富,更像是饭后甜点。

随着业务不断发展,B站的评论系统逐渐组件化、平台化;

通过持续演进架构设计,管理不断上升的系统复杂度,从而更好地满足各类用户的需求。

评论的基础功能模块是相对稳定的。

  1. 发布评论:支持无限盖楼回复。
  2. 读取评论:按照时间、热度排序;显示评论数、楼中楼等。
  3. 删除评论:用户删除、UP主删除等。
  4. 评论互动:点赞、点踩、举报等。
  5. 管理评论:置顶、精选、后台运营管理(搜索、删除、审核等)。

结合B站以及其他互联网平台的评论产品特点,评论一般还包括一些更高阶的基础功能:

  1. 评论富文本展示:例如表情、@、分享链接、广告等。
  2. 评论标签:例如UP主点赞、UP主回复、好友点赞等。
  3. 评论装扮:一般用于凸显发评人的身份等。
  4. 热评管理:结合AI和人工,为用户营造更好的评论区氛围。

7.1 总体的架构设计

评论系统 中台,从总体的架构上来区分,分为:

(1)接入层

(2)服务层

(3)异步任务层

(4)cache层

(5)DB层

7.2 接入层架构 reply-interface

reply-interface是评论系统的接入层,主要服务于两种调用者:

一是客户端的评论组件,

二是基于评论系统做二次开发或存在业务关联的其他业务后端。

面向移动端/WEB场景,设计一套基于视图模型的API,利用客户端提供的布局能力,接入层负责组织业务数据模型,并转换为视图模型,编排后下发给客户端。

面向服务端场景,接入层设计的API需要体现清晰的系统边界,最小可用原则对外提供数据,同时做好安全校验和流量控制。

接入层整个业务数据模型组装,分为两个步骤:

一是服务编排,

二是数据组装。

服务编排拆的架构为:

(1)对服务进行分层,分为若干个层级,

(2)前置依赖通过流水线调用,

(3)同一层级的可以并发调用,结构性提升了复杂调用场景下的接口性能下限;

(4)针对不同依赖服务所提供的SLA不同,设置不同的降级处理、超时控制和服务限流方案,保证少数弱依赖抖动甚至完全不可用情况下评论服务可用。

SLA一般指服务级别协议。服务级别协议是指提供服务的企业与客户之间就服务的品质、水准、性能等方面所达成的双方共同认可的协议或契约。

7.3 服务层架构

7.3.1 评论管理服务层reply-admin

评论管理服务层,为多个内部管理后台提供服务。

运营人员的数据查询具有:

  1. 组合、关联查询条件复杂;
  2. 刚需关键词检索能力;
  3. 写后读的可靠性与实时性要求高等特征。

此类查询需求,ES几乎是不二选择。

但是由于业务数据量较大,需要为多个不同的查询场景建立多种索引分片,且数据更新实时性不高。

因此,我们基于ES做了一层封装,提供统一化的数据检索能力,并结合在线数据库刷新部分实时性要求较高的字段。

7.3.2 评论基础服务 reply-service 架构设计

评论基础服务层,专注于评论功能的原子功能,例如:

  • 查询评论列表
  • 删除评论等。

这一层的特点是:

  • 较少做业务逻辑变更的,
  • 极高的可用性
  • 极高性能吞吐。

这一层采用了多种高性能方案:

  • 多级缓存
  • 布隆过滤器
  • 热点探测等。

7.3.3 异步任务层reply-job 架构设计

异步任务层,主要有两个职责:

  1. 为原子的业务操作操作,提供异步协助

与reply-service协同,为评论基础功能的原子化实现做架构上的补充。

  1. 异步削峰处理

为 长耗时/高吞吐的调用, 做异步化/削峰处理

职责1:提供异步协助

为原子的业务操作操作,提供异步协助, 最典型的案例就是缓存的更新。

一般采用Cache Aside模式,先读缓存,再读DB;

Cache Aside模式下的缓存的重建策略:就是读请求未命中缓存穿透到DB,从DB读取到内容之后反写缓存。

这一套流程对外提供了一个原子化的数据读取功能。

但由于部分缓存数据项的重建代价较高,比如评论列表。

为啥呢?

由于列表是分页的,缓存重建时会启用预加载,也就是要多加载几页,

如果短时间内大量请求缓存未命中,并且多个服务节点的同时重建缓存,容易造成DB抖动。

解决方案是啥?

利用消息队列+reply-job ,实现单个评论列表异步重建,只重建一次缓存。

另外呢,reply-job还作为数据库binlog的消费者,执行缓存的更新操作。

职责2:异步削峰处理

与reply-interface协同,为 长耗时/高吞吐的调用,做异步化/削峰处理

诸如评论发布等操作,基于安全/策略考量,会有非常重的前置调用逻辑。

对于用户来说,这个长耗时几乎是不可接受的。同时,时事热点容易造成发评论的瞬间峰值流量。

因此,reply-interface在处理完一些必要校验逻辑之后,会通过消息队列送至reply-job异步处理,包括送审、写DB、发通知等。

那么异步处理后用户体验是如何保证的呢?

首先是当次交互,返回最新数据。

C端的发评接口会返回展示新评论所需的数据内容,客户端据此展示新评论,完成一次用户交互。

其次,控制延迟时长,如果太长则进行预警和调优

若用户重新刷新页面,因为发评的异步处理端到端延迟基本在2s以内,此时所有数据已准备好,不会影响用户体验。

7.3.4 消息队列的保证有序

利用了消息队列的「有序」特性,将单个评论区内的发评串行处理,避免了并行处理导致的一些数据错乱风险。

一个有趣的问题是,早年间评论显示楼层号,楼层号实际是计数器,且在一个评论区范围内不能出现重复。

因此,这个楼层发号操作必须是在一个评论区范围内串行的(或者用更复杂的锁实现),否则两条同时发布的评论,获取的楼层号就是重复的。

而分布式部署+负载均衡的网关,处理发评论请求是无法实现这种串行的,因此需要放到消息队列中处理。

二、粉丝福利

我根据我从小白到架构师多年的学习经验整理出来了一份50W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴斯我一下,或者评论区扣“求分享

  • 32
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值