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

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

哔哩哔哩技术.

提供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.mzph.cn/bicheng/68651.shtml

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

相关文章

蓝桥杯 阶乘的和(C++完整代码+详细分析)

题目描述 原题链接 阶乘的和 问题描述 给定 n 个数 Ai​,问能满足 m! 为 ∑(Ai!) 的因数的最大的 m 是多少。其中 m! 表示 m 的阶乘,即 123⋯m。 输入格式 输入的第一行包含一个整数 n。 第二行包含 n 个整数,分别表示 Ai​,相…

2024:成长、创作与平衡的年度全景回顾

文章目录 1.前言2.突破自我:2024年个人成长与关键突破3.创作历程:从构想到落笔,2024年的文字旅程4.生活与学业的双重奏:如何平衡博客事业与个人生活5.每一步都是前行:2024年度的挑战与收获6.总结 1.前言 回首2024年&a…

统信V20 1070e X86系统编译安装mysql-5.7.44版本以及主从构建

设备信息 操作系统版本架构CPU内存备注统信UOS V20 1070eX864C8G此配置仅做编译安装验证,持续运行或数据量增长大请自行评估资源配置。统信UOS V20 1070eX864C8G 资源包 该包包含mysql-5.7.44源码包、boost资源包、统信编译mysql-5.7.44安装包 通过网盘分享的文件…

4 AXI USER IP

前言 使用AXI Interface封装IP,并使用AXI Interface实现对IP内部寄存器进行读写实现控制LED的demo,这个demo是非常必要的,因为在前面的笔记中基本都需哟PS端与PL端就行通信互相交互,在PL端可以通过中断的形式来告知PS端一些事情&…

RoCE网络及其协议栈详解(没有中间商赚差价的网络)

引言 随着数据中心对高性能、低延迟通信需求的不断增长,传统的TCP/IP以太网连接已经难以满足现代应用的要求。为了解决这些问题,RDMA(Remote Direct Memory Access)技术应运而生。RDMA是一种允许网络中的不同计算机直接访问对方内…

回归预测 | MATLAB基于TCN-BiGRU时间卷积神经网络结合双向门控循环单元多输入单输出回归预测

效果一览 基本介绍 回归预测 | MATLAB基于TCN-BiGRU时间卷积神经网络结合双向门控循环单元多输入单输出回归预测 一、引言 1.1、研究背景及意义 在当今数据驱动的时代,时间序列预测已成为金融、气象、工业控制等多个领域的关键技术。随着人工智能和机器学习技术的…

HTML<img>标签

例子 如何插入图片&#xff1a; <img src"img_girl.jpg" alt"Girl in a jacket" width"500" height"600"> 下面有更多“自己尝试”的示例。 定义和用法 该<img>标签用于在 HTML 页面中嵌入图像。 从技术上讲&#x…

Linux--运维

Mysql主从同步 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其他主机&#xff08;slaves&#xff09;上&#xff0c;并重新执行一遍来执行 复制过程中一台服务器充当主服务器&#xff0c;而其他一个或多个其他服务器充当从服务器 为什么要做主从复制 …

浅谈计算机网络03 | 现代网络组成

现代网络组成 一 、网络生态体系1.1网络生态系统的多元主体1.2 网络接入设施的多样类型 二、现代网络的典型体系结构解析三、高速网络技术3.1 以太网技术3.2 Wi-Fi技术的深度剖析3.2.1 应用场景的多元覆盖3.2.2 标准升级与性能提升 3.3 4G/5G蜂窝网的技术演进3.3.1 蜂窝技术的代…

[gpu驱动] H200 nvidia-fabricmanager-550升级到nvidia-fabricmanager-565报错,升级步骤

报错日志: root@h1-12-gpu:/home/canopy# apt install nvidia-fabricmanager-565 Reading package lists... Done Building dependency tree... Done Reading state information... Done Some packages could not be installed. This may mean that you have requested an imp…

LeetCode 110.平衡二叉树

题目描述 给定一个二叉树&#xff0c;判断它是否是平衡二叉树。 示例 1&#xff1a; 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&#xff1a;false 示例 3&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;true 提示&#xff1a; …

如何在前端给视频进行去除绿幕并替换背景?-----Vue3!!

最近在做这个这项目奇店桶装水小程序V1.3.9安装包骑手端V2.0.1小程序前端 最近&#xff0c;我在进行前端开发时&#xff0c;遇到了一个难题“如何给前端的视频进行去除绿幕并替换背景”。这是一个“数字人项目”所需&#xff0c;我一直在冥思苦想。终于有了一个解决方法…

【Java 数据导出到 Word实现方案】使用EasyPOI 工具包进行简易的word操作

文章目录 前言工具包调研实现方案主要步骤&#xff1a;1. 导入 EasyPOI 依赖2. 创建 Word 文件3. 添加数据到 Word 文件4. 保存文件到本地 使用过程中可能遇到的问题总结 前言 最近业务方说周报、月报让他们很头疼&#xff0c;每次都要统计数据后&#xff0c;手动录入到word文…

华为HuaweiCloudStack(一)介绍与架构

本文简单介绍了华为HCS私有云解决方案&#xff0c;并从下至上介绍HCS的整体架构&#xff0c;部署架构、部署方式等内容。 目录 HCS简介 HCS架构 纵向结构 ?管理平台类型 HCS节点类型 FusionSphere OpenStack CPS ServiceOM SC 运营面 OC 运维面 HCS部署架构 regi…

(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)

一、四大坐标系介绍 1&#xff0c;世界坐标系 从这个世界&#xff08;world&#xff09;的视角来看物体 世界坐标系是3D空间坐标&#xff0c;每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw​,Yw​,Zw​)表示 2&#xff0c;相机坐标系 相机本身具有一个坐标系&…

openwrt下oaf插件编译安装,实现上网行为监控

文章目录 入门级APP青少年模式设备屏幕使用时间电脑浏览器使用时间限制Surpal 介绍安装使用进阶级专业级旁路由方案openwrt路由器固件编译OAF(Open App Filter)安装编译带有oaf的固件固件烧写设备上电启动应用特征库设置黑白名单及应用访问限制骨灰级ref守护孩子视力,用科技“…

目标检测新视野 | YOLO、SSD与Faster R-CNN三大目标检测模型深度对比分析

目录 引言 YOLO系列 网络结构 多尺度检测 损失函数 关键特性 SSD 锚框设计 损失函数 关键特性 Faster R-CNN 区域建议网络&#xff08;RPN&#xff09; 两阶段检测器 损失函数 差异分析 共同特点 基于深度学习 目标框预测 损失函数优化 支持多类别检测 应…

Linux之网络套接字

Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…

Mysql常见问题处理集锦

Mysql常见问题处理集锦 root用户密码忘记&#xff0c;重置的操作(windows上的操作)MySQL报错&#xff1a;ERROR 1118 (42000): Row size too large. 或者 Row size too large (&#xff1e; 8126).场景&#xff1a;报错原因解决办法 详解行大小限制示例&#xff1a;内容来源于网…

ReactiveSwift 简单使用

记录 ReactiveSwift 简单使用 导入 ReactiveSwift 库创建 TestViewModel 文件 enum JKTypeType: Int {case cloudcase devicecase weater }// 通过监听属性变化 class TestViewModel: NSObject {lazy var recordType: Property<JKTypeType> {return Property(recordTy…