B站评论系统的多级存储架构

news2025/2/24 1:16:17

以下文章来源于哔哩哔哩技术 ,作者业务

哔哩哔哩技术.

提供B站相关技术的介绍和讲解

1.  背景

评论是 B站生态的重要组成部分,涵盖了 UP 主与用户的互动、平台内容的推荐与优化、社区文化建设以及用户情感满足。B站的评论区不仅是用户互动的核心场所,也是平台运营和用户粘性的关键因素之一,尤其是在与弹幕结合的情况下,成为平台的标志性特色。

在社会热点事件发生时,评论区的读写流量会急剧增加,直接影响业务运行,对用户体验、内容创作和社区文化等多个方面产生负面影响,所以评论服务的稳定性至关重要。

评论系统对缓存命中率要求非常高,一旦发生缓存失效,大量请求会直接访问 TiDB,如果 TiDB 出现问题,将导致评论服务不可用。所以评论需要构建一套可靠的容灾系统,并具备自动降级能力,以提升评论服务的整体稳定性。

图片

图片

2. 架构设计

评论系统架构主要依赖 Redis 缓存和 TiDB 存储,列表接口中依赖多种排序索引,如点赞序、时间序、热度序等,这些索引通过 Redis 的 Sorted Set 数据结构进行存储。

在大评论区中查询这些排序索引,当 Redis 缓存 miss 时需要回源 TiDB 查询,因数据量过大、查询耗时较长,慢查询会占用大量 CPU 和内存,进而导致其他查询的延迟或阻塞,严重影响整个 TiDB 的吞吐量和性能。例如查询点赞序排序索引:

SELECT id FROM reply WHERE ... ORDER BY like_count DESC LIMIT m,n

为了避免 TiDB 故障导致评论服务不可用,我们希望建立一套新的存储系统,解决 TiDB 单点故障问题。该系统不仅为业务提供容灾能力和自动降级通道,还能在大流量查询场景下提供更优的查询性能,从而提升整体评论服务的稳定性。

基于 B站自研的泰山 KV 存储(Taishan),我们搭建了「多级存储架构」,整体设计方案的核心思路包括:

  • 将排序索引的存储从「结构化」转为「非结构化」

  • 将排序索引查询从「SQL」转换为性能更高的「NoSQL」

  • 通过「写场景的复杂度」来换取「更优的读场景性能」

图片

3. 存储设计

 存储模型

在评论的业务场景中,我们抽象了两种数据模型:排序索引(Index)、评论物料(KV)

抽象数据模型

TiDB 模型

Taishan 模型

说明

Index

Secondary Index

Sorted Set

排序索引,例如点赞序、时间序的排序索引

KV

Primary Key & Row

Key-Value

包含元数据、内容等必要的评论物料

下图以按点赞序排序的前 10 条评论为例,展示了使用 Index + KV 模型实现的具体思路。在更复杂的推荐排序场景中,依然可以通过此模型来实现。具体流程是:首先通过排序索引召回一批评论 ID,再通过推荐算法对这些 ID 进行重排,最终根据重排后的 ID 获取评论详情并返回给用户。

图片

将领域对象的存储建模划分为 Index 和 KV 两种模型,可以利用不同的底层存储结构来分别优化查询、扫描、排序、分页等场景。使用 Redis 或 Memcache 作为缓存构建 KV 模型,提升查询性能,使用 Redis 的 Sorted Set 构建 Index 模型,支持增量数据实时更新排序索引,并提供极高效的分页查询性能。在关键词搜索场景,可采用 ElasticSearch 作为检索索引,避免在原始数据库上进行低效的遍历操作;

基于 KV 作为唯一事实表,采用同步全量数据和实时捕获增量数据的方法,将原始数据转换为下游索引表。这样可以灵活构建定制化的排序索引,以应对多变的评论业务需求。同时该方案在不影响原有业务逻辑和存储资源的情况下,实现了业务、代码和数据的解耦。

如果索引的定义和实现不再局限于源数据库的原生索引,而是扩展到应用逻辑,并在其他存储上自行维护物化视图,这必然会带来额外的理解和维护成本,同时引入一致性的难题。然而考虑到评论业务的数据量级和复杂度,该方案的整体优势仍然大于劣势。所以我们需要新的存储方案,既支持基本的 Index 和 KV 模型,又能满足高性能、可用性和扩展性等方面的需求。

数据类型

我们期望将数据类型从 SQL 转向 NoSQL,因为 NoSQL 提供了更灵活的数据模型,意味着更可解释的执行计划和更高的优化潜力。例如 Taishan 查询 Redis Sorted Set 的 P999 耗时约 10ms,查询 KV 的 P999 耗时约 5ms,这种高效的查询性能对评论业务尤为重要。

相比 TiDB,Taishan 不支持 ACID 事务、二级索引等功能,提供的能力更为精简。基于之前的经验和问题,有时候“less is more”反而能带来更高的可用性。以下是评论业务在使用 TiDB 时遇到的一些问题:

  1. MVCC 机制:TiDB 的事务实现基于 MVCC 机制,当新写入的数据覆盖旧数据时,旧数据不会被删除,而是以时间戳区分多个版本,并通过定期 GC 清理不再需要的数据。在热门评论区中,频繁更新点赞数时,排序索引的 MVCC 历史版本过多,导致 TiDB 的读写性能下降。相比之下,不支持 MVCC 的 Taishan 在查询排序索引时能提供更高效、更稳定的性能;

  2. 分片策略:TiDB 不直接支持完全自定义的分片策略,而 Taishan 支持哈希标签(hash tags),可以在 Key 中使用大括号 { } 指定参与哈希计算的部分。这样多个 Key 可以使用相同的 ID 进行分区路由,确保同一评论区的评论位于同一分片。在批量查询评论时,这能大幅降低扇出度,减少长尾耗时的影响。而对于可能出现热点的场景,Taishan 可以选择不使用哈希标签,从而打散请求,为性能要求高的评论业务提供更大的优化空间。

基于现有评论在 TiDB 中的存储结构和索引设计,以时间序和点赞序为例,列举 Taishan 的数据模型如下:

图片

4.  数据一致性

从 TiDB 的结构化数据转变为 Taishan 的非结构化数据,目前缺乏现成的同步工具,需要业务自行实现数据同步。然而数据同步过程中可能出现数据丢失、写入失败、写冲突、顺序错乱和同步延迟等问题,导致数据不一致。由于评论业务对数据一致性要求较高,我们需要一套可靠的数据同步方案,确保两者之间的数据一致性。

重试队列

针对写失败的问题,我们通过引入重试队列来解决,将写失败的请求放入队列中进行异步重试,确保数据不会因暂时性问题而永久丢失。引入重试队列可能会导致写并发产生数据竞争,进而引发数据最终不一致。虽然可以通过 CAS(Compare-and-Swap)来解决数据竞争问题,确保“读取-修改-写回”操作的原子性,但这也可能带来乱序问题。

图片

乱序问题

由于写数据有多个场景来源,包括 binlog 同步、重试队列,这些并发写操作导致数据错误,此外 MQ 消息因 rebalance 可能会被重新消费,导致消息回放,所以数据同步过程中不仅需要保证幂等性,还必须确保消息的顺序性:

例如并发写的场景,评论 A 被点赞两次,点赞数(like_count)为 2,TiDB 会生成两条 binlog 数据:

  1. 第一条数据 binlog_0 中,like_count = 1,由于网络原因写入失败,数据被转入重试队列进行异步处理。

  2. 第二条数据 binlog_1 中,like_count = 2,写入成功,评论 A 的 like_count 更新为 2,符合预期。

  3. 然而,重试队列继续处理 binlog_0,由于无法保证两个写操作的顺序,写入后 like_count 被更新为 1,导致数据不一致。

回退问题

在消息回放场景中,假设评论 A 被点赞三次,点赞数(like_count)为 3,TiDB 会生成三条 binlog 数据 [a, b, c]。正常情况下,这三条数据会被顺序消费并处理。如果在消费过程中发生 rebalance,导致消息回放,这三条数据会被重新消费,从而导致点赞数出现短暂的数据回退。

版本号

为避免乱序和回退问题导致的数据不一致,我们引入了版本号机制,每次评论数据变更时,版本号会递增。

UPDATE reply SET like_count=like_count+1, version=version+1 WHERE id = xxx

在 CAS 写操作时,将 binlog 数据中的 version 值与 Taishan 中数据的 version 值进行比对。如果 binlog 中的 version 值大于或等于当前数据的 version 值,则执行更新;否则认为该数据为过期数据,予以丢弃。

图片

 对账系统

根据 CAP 理论,在保证可用性(Availability)和分区容忍性(Partition)之后,分布式系统无法完全保证一致性(Consistency)。尽管引入了重试机制、CAS 和版本号机制,但由于网络调用的不可避免失败,评论数据之间难免会出现长期或短期的不一致状态。一旦发生不一致,需要有一套对账机制来及时发现并修复这些不一致的数据。

实时对账

通过 TiDB 的 Binlog 事件驱动,使用延迟队列延迟 n 秒后消费, binlog 数据关联查询 Taishan 数据,并对比两者的数据。对于发现的异常数据,进行通知并触发数据修复。

离线对账

利用 TiDB 和 Taishan 的数仓离线数据,进行 T+1 数据对比,验证数据的最终一致性。

图片

5.  降级策略

评论业务对可用性的要求非常高,尤其是在高并发、实时性强、用户互动频繁的场景下。通过搭建多级存储架构,我们能够在 TiDB 故障时自动降级到 Taishan,确保评论服务持续正常运行,我们的目标是实现每个请求的自动降级。

每次请求时,首先尝试从主存储获取数据。当主存储服务返回错误或长时间无响应时,降级到次要存储服务获取数据。在设计降级策略时,通常采用串行或并行方式,分别影响系统的响应时间和复杂性,而且整体耗时不能超过上游的超时限制,否则降级无效。

降级策略

优势

劣势

串行

简单

耗时长,容易整体超时

并行

耗时短

多1倍的请求,浪费资源

串行策略无法满足评论业务对响应时间的要求,而并行策略则可能浪费资源。所以我们选择了「对冲策略」(Hedging Policy)。在主节点请求超时后,我们会发起一个延迟x毫秒「备份请求」(backup request)到次节点。如果主节点返回成功,则直接返回结果,否则等待次节点的响应,优先选择主节点的结果。通过根据主次节点的耗时特性设置合理的延迟阈值,我们在整体响应时间和资源消耗之间达到了平衡。

图片

在实际生产环境中,我们根据具体业务场景设定 TiDB 和 Taishan 的主次关系。对于对数据实时性敏感、查询轻量的场景,设定 TiDB 为主存储,Taishan 为次存储;而对于数据实时性要求较低、大 SQL 查询的场景,则设定 Taishan 为主存储,TiDB 为次存储。

某天凌晨,TiDB 底层的 TiKV 节点宕机,在 TiKV 自愈期间,系统自动降级到 Taishan,评论业务未受影响,线上服务持续稳定运行。

图片

6.  总结与展望

B站评论服务对社区业务和用户体验至关重要。我们不仅致力于持续提升评论服务的稳定性,还不断优化评论业务,以便用户能够看到更优质的评论内容,从而增强归属感和认同感,提供更好的消费体验。

最后,发一条友善的评论吧,遇见和你一样有趣的人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2280016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电子科大2024秋《大数据分析与智能计算》真题回忆

考试日期:2025-01-08 课程:成电信软学院-大数据分析与智能计算 形式:开卷 考试回忆版 简答题(4*15) 1. 简述大数据的四个特征。分析每个特征所带来的问题和可能的解决方案 2. HDFS的架构的主要组件有哪些&#xff0…

多选multiple下拉框el-select回显问题(只显示后端返回id)

首先保证v-model的值对应options数据源里面的id <el-form-item prop"subclass" label"分类" ><el-select v-model"formData.subclass" multiple placeholder"请选择" clearable :disabled"!!formData.id"><e…

JavaWeb开发(十五)实战-生鲜后台管理系统(二)注册、登录、记住密码

1. 生鲜后台管理系统-注册功能 1.1. 注册功能 &#xff08;1&#xff09;创建注册RegisterServlet&#xff0c;接收form表单中的参数。   &#xff08;2&#xff09;service创建一个userService处理业务逻辑。   &#xff08;3&#xff09;RegisterServlet将参数传递给ser…

【MySQL系列文章】Linux环境下安装部署MySQL

前言 本次安装部署主要针对Linux环境进行安装部署操作,系统位数64 getconf LONG_BIT 64MySQL版本&#xff1a;v5.7.38 一、下载MySQL MySQL下载地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 二、上传MySQL压缩包到Linuxx环境&#xff0c…

嵌入式硬件篇---基本组合逻辑电路

文章目录 前言基本逻辑门电路1.与门&#xff08;AND Gate&#xff09;2.或门&#xff08;OR Gate&#xff09;3.非门&#xff08;NOT Gate&#xff09;4.与非门&#xff08;NAND Gate&#xff09;5.或非门&#xff08;NOR Gate&#xff09;6.异或门&#xff08;XOR Gate&#x…

基于微信小程序的手机银行系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

C++ List 容器:实现原理深度解析

1.基本结构 1.1list底层 list底层是一个双向链表&#xff0c;每个节点包含三个主要部分&#xff1a;存储的数据&#xff0c;指向前一个节点和后一个节点的指针。我们首先定义一个 list_node 结构体来描述链表节点。 template <class T> struct list_node {T _data;lis…

在Spring Boot中使用SeeEmitter类实现EventStream流式编程将实时事件推送至客户端

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

Maven下载配置

目录 Win下载配置maven的环境变量 Mac下载安装配置环境变量 MavenSetting.xml文件配置 Win 下载 https://maven.apache.org/ 在主页面点击Download 点击archives 最好不要下载使用新版本&#xff0c;我使用的是maven-3.6.3&#xff0c;我们点击页面下方的archives&#xff0…

小程序获取微信运动步数

1、用户点击按钮&#xff0c;在小程序中触发getuserinfo方法&#xff0c;获取用户信息 <scroll-view class"scrollarea" scroll-y type"list"><view class"container"><button bind:tap"getLogin">获取</button&…

OSCP - Proving Grounds - BullyBox

主要知识点 如果发现有域名&#xff0c;则可以加入/etc/hosts后重新执行nmap,nikto等扫描dirsearch的时候可以使用完整一些的字典文件&#xff0c;避免漏掉信息.git dump 具体步骤 执行nmap 扫描&#xff0c;发现 80和22端口开放,访问后发现被重定向到 bullybox.local Star…

MIAOYUN信创云原生项目亮相西部“中试”生态对接活动

近日&#xff0c;以“构建‘中试’生态&#xff0c;赋能科技成果转化”为主题的“科创天府智汇蓉城”西部“中试”生态对接活动在成都高新区菁蓉汇隆重开幕。活动分为成果展览、“中试”生态主场以及成果路演洽谈对接三大板块。在成果展览环节&#xff0c;成都元来云志科技有限…

计算机网络 (47)应用进程跨越网络的通信

前言 计算机网络应用进程跨越网络的通信是一个复杂而关键的过程&#xff0c;它涉及多个层面和组件的协同工作。 一、通信概述 计算机网络中的通信&#xff0c;本质上是不同主机中的应用进程之间的数据交换。为了实现这种通信&#xff0c;需要借助网络协议栈中的各层协议&#x…

封装svg图片展示及操作组件——svgComponent——js技能提升

template部分 <template><div class"canvas-wrapper" ref"canvasWrapper"><svg:viewBox"computedViewBox"ref"svgCanvas"xmlns"http://www.w3.org/2000/svg"xmlns:xlink"http://www.w3.org/1999/xlink…

大数据,Hadoop,HDFS的简单介绍

大数据 海量数据&#xff0c;具有高增长率、数据类型多样化、一定时间内无法使用常规软件工具进行捕捉、管理和处理的数据集 合 大数据的特征: 4V Volume : 巨大的数据量 Variety : 数据类型多样化 结构化的数据 : 即具有固定格式和有限长度的数据 半结构化的数据 : 是…

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成

EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成 1所有的材料都可以在EAMM: One-Shot Emotional Talking Face via Audio-Based Emotion-Aware Motion Model网站上找到。 摘要 尽管音频驱动的对话人脸生成技术已取得显著进展&#xff0c;但现有方法要么忽…

基于STM32的智能门锁安防系统(开源)

目录 项目演示 项目概述 硬件组成&#xff1a; 功能实现 1. 开锁模式 1.1 按键密码开锁 1.2 门禁卡开锁 1.3 指纹开锁 2. 功能备注 3. 硬件模块工作流程 3.1 步进电机控制 3.2 蜂鸣器提示 3.3 OLED显示 3.4 指纹与卡片管理 项目源代码分析 1. 主程序流程 (main…

2024年度总结:从后端Java到全栈成长的蜕变

目录 前言1. 用数据与实践书写成长篇章2. 技术与生活的双重蜕变3. 技术的进阶与生活的绽放 前言 今年是我入行的第十年&#xff0c;也是记录在CSDN平台上的第五年。这五年来&#xff0c;我始终坚持记录成长的点滴&#xff0c;将个人事业与博客创作紧密相连。一路走来&#xff0…

行人识别检测数据集,yolo格式,PASICAL VOC XML,COCO JSON,darknet等格式的标注都支持,准确识别率可达99.5%

作者简介&#xff1a; 高科&#xff0c;先后在 IBM PlatformComputing从事网格计算&#xff0c;淘米网&#xff0c;网易从事游戏服务器开发&#xff0c;拥有丰富的C&#xff0c;go等语言开发经验&#xff0c;mysql&#xff0c;mongo&#xff0c;redis等数据库&#xff0c;设计模…

Web3 游戏周报(1.13 - 1.19)

回顾上周的区块链游戏概况&#xff0c;查看 Footprint Analytics 与 ABGA 最新发布的数据报告。 【1.13–1.19】Web3 游戏行业动态 索尼区块解决方案实验室 (Sony BSL) 宣布其以太坊 L2 区块链 Soneium 主网上线。Hyve Labs 融资 275 万美元&#xff0c;推动 Web3 游戏基础设…