MySQL扛不住?B站千亿级点赞系统服务架构设计

标签: | 发表时间:2023-02-26 14:57 | 作者:
出处:https://dbaplus.cn

为了在提供上述能力的前提下经受住流量、存储、容灾三大压力,点赞目前的系统实现方式如下:

 

 

 1、系统架构简介

 

图片

 

整个点赞服务的系统可以分为五个部分

 

  • 流量路由层(决定流量应该去往哪个机房)

  • 业务网关层(统一鉴权、反黑灰产等统一流量筛选)

  • 点赞服务(thumbup-service),提供统一的RPC接口

  • 点赞异步任务(thumbup-job)

  • 数据层(db、kv、redis)

 

下文将重点分享下 数据存储层、点赞服务层(thumbup-service)与  异步任务层(thumbup-job)的系统设计

 

 

2、三级数据存储

 

基本数据模型:

 

  • 点赞记录表:记录用户在什么时间对什么实体进行了什么类型的操作(是赞还是踩,是取消点赞还是取消点踩)等

     

  • 点赞计数表:记录被点赞实体的累计点赞(踩)数量

 

(1)第一层存储:DB层 - (TiDB)

 

点赞系统中最为重要的就是点赞记录表(likes)和点赞计数表(counts),负责整体数据的持久化保存,以及提供缓存失效时的回源查询能力。

 

  • 点赞记录表 - likes : 每一次的点赞记录(用户Mid、被点赞的实体ID(messageID)、点赞来源、时间)等信息,并且在Mid、messageID两个维度上建立了满足业务求的联合索引。

     

  • 点赞数表 - counts : 以业务ID(BusinessID)+实体ID(messageID)为主键,聚合了该实体的点赞数、点踩数等信息。并且按照messageID维度建立满足业务查询的索引。

     

  • 由于DB采用的是分布式数据库TiDB,所以对业务上无需考虑分库分表的操作

 

(2)第二层存储

 

缓存层Cache:点赞作为一个高流量的服务,缓存的设立肯定是必不可少的。点赞系统主要使用的是CacheAside模式。这一层缓存主要基于Redis缓存:以点赞数和用户点赞列表为例

 

①点赞数

 

图片

 

  •  
  •  
    key-value= count:patten:{business_id}:{message_id} - {likes},{disLikes}    用业务ID和该业务下的实体ID作为缓存的Key,并将点赞数与点踩数拼接起来存储以及更新

 

②用户点赞列表

 

图片

 

  •  
  •  
  •  
    key-value= user:likes:patten:{mid}:{business_id} - member(messageID)-score(likeTimestamp)    * 用mid与业务ID作为key,value则是一个ZSet,member为被点赞的实体ID,score为点赞的时间。当改业务下某用户有新的点赞操作的时候,被点赞的实体则会通过 zadd的方式把最新的点赞记录加入到该ZSet里面来    为了维持用户点赞列表的长度(不至于无限扩张),需要在每一次加入新的点赞记录的时候,按照固定长度裁剪用户的点赞记录缓存。该设计也就代表用户的点赞记录在缓存中是有限制长度的,超过该长度的数据请求需要回源DB查询

 

(3)第三层存储

 

LocalCache - 本地缓存

 

  • 本地缓存的建立,目的是为了应对缓存热点问题。

     

  • 利用最小堆算法,在可配置的时间窗口范围内,统计出访问最频繁的缓存Key,并将热Key(Value)按照业务可接受的TTL存储在本地内存中。

     

  • 其中热点的发现之前也有同步过:https://mp.weixin.qq.com/s/C8CI-1DDiQ4BC_LaMaeDBg

 

(4)针对TIDB海量历史数据的迁移归档

 

迁移归档的原因(初衷),是为了减少TIDB的存储容量,节约成本的同时也多了一层存储,可以作为灾备数据。

 

以下是在KV数据库(taishan)中点赞的数据与索引的组织形式:

 

①点赞记录

 

  •  
    1_{mid}_${business_id}_${type}_${message_id}=> {origin_id}_{mtime}

 

②用户点赞列表索引

 

图片

 

  •  
    2_{mid}_${business_id}_${type}_${mtime}_{message_id} => {origin_id}

 

③实体维度点赞记录索引

 

图片

 

  •  
    3_{message_id}_${business_id}_${type}_${mtime}_${mid}=>{origin_id}

 

 

 3、存储层的优化和思考

 

作为一个典型的大流量基础服务,点赞的存储架构需要最大程度上满足两个点:

 

(1)满足业务读写需求的同时具备最大的可靠性

 

(2)选择合适的存储介质与数据存储形态,最小化存储成本

 

从以上两点触发,考虑到KV数据在业务查询以及性能上都更契合点赞的业务形态,且TaiShan可以水平扩容来满足业务的增长。点赞服务从当前的关系型数据库(TiDB)+ 缓存(Redis)逐渐过渡至KV型数据库(Taishan)+ 缓存(Redis),以具备更强的可靠性。

 

同时TaiShan作为公司自研的KV数据库,在成本上也能更优于使用TiDB存储。

 

 

 4、点赞服务层(thumbup-service)

 

作为面对C端流量的直接接口,在提供服务的同时,需要思考在面对各种未知或者可预知的灾难时,如何尽可能提供服务

 

  • 存储(db、redis等)的容灾设计(同城多活)

 

在DB的设计上,点赞服务有两地机房互为灾备,正常情况下,机房1承载所有写流量与部分读流量,机房2承载部分读流量。当DB发生故障时,通过db-proxy(sidercar)的切换可以将读写流量切换至备份机房继续提供服务。

 

图片

 

图片

 

在缓存(Redis)上,点赞服务也拥有两套处于不同机房的集群,并且通过异步任务消费TiDB的binLog维护两地缓存的一致性。可以在需要时切换机房来保证服务的提供,而不会导致大量的冷数据回源数据库。

 

服务的容灾与降级

 

(以点赞数、点赞状态、点赞列表为例),点赞作为一个用户强交互的社区功能服务,对于灾难发生时用户体验的保证是放在第一位的。所以针对重点接口,我们都会有兜底的数据作为返回。

 

多层数据存储互为灾备

 

  • 点赞的热数据在redis缓存中存有一份。

     

  • kv数据库中存有全量的用户数据,当缓存不可用时,KV数据库会扛起用户的所有流量来提供服务。

     

  • TIDB目前也存储有全量的用户数据,当缓存、KV均不可用时,tidb会依托于限流,最大程度提供用户数据的读写服务。

     

  • 因为存在多重存储,所以一致性也是业务需要衡量的点。

 

  • 首先写入到每一个存储都是有错误重试机制的,且重要的环节,比如点赞记录等是无限重试的。

     

  • 另外,在拥有重试机制的场景下,极少数的不同存储的数据不一致在点赞的业务场景下是可以被接受的

 

  • 多地方机房互为灾备

 

  • 点赞机房、缓存、数据库等都在不同机房有备份数据,可以在某一机房或者某地中间件发生故障时快速切换。

 

  • 点赞重点接口的降级

 

  • 点赞数、点赞、列表查询、点赞状态查询等接口,在所有兜底、降级能力都已失效的前提下也不会直接返回错误给用户,而是会以空值或者假特效的方式与用户交互。后续等服务恢复时,再将故障期间的数据写回存储。

 

 

 5、异步任务层(thumbup-job)

 

  • 异步任务主要作为点赞数据写入、刷新缓存、为下游其他服务发送点赞、点赞数消息等功能

 

首先是最重要的用户行为数据(点赞、点踩、取消等)的写入。搭配对数据库的限流组件以及消费速度监控,保证数据的写入不超过数据库的负荷的同时也不会出现数据堆积造成的C数据端查询延迟问题。

 

图片

 

  • 缓存刷新:点赞状态缓存、点赞列表缓存、点赞计数缓存

     

  • 同步点赞消息

 

  • 点赞事件异步消息、点赞计数异步消息

 

  • 针对 WriteBack方式的思考

 

  • 由于目前点赞系统异步处理能力或者说速率是能够满足业务的。所以当前写DB与写缓存都放在异步流程中。

     

  • 后续随着流量的增加,实施流程中写缓存,再由异步Job写入持久层相对来说是一个更好的方案。

 

点赞job对binLog的容灾设计

 

由于点赞的存储为TiDB,且数据量较大。在实际生产情况中,binLog会偶遇数据延迟甚至是断流的问题。为了减少binLog数据延迟对服务数据的影响。服务做了以下改造。

 

  • 监控:

 

首先在运维层面、代码层面都对binLog的实时性、是否断流做了监控

 

  • 应对:

 

脱离binlog,由业务层(thumb-service)发送重要的数据信息(点赞数变更、点赞状态事件)等。当发生数据延迟时,程序会自动同时消费由thumbup-service发送的容灾消息,继续向下游发送。

 

三、未来规划

 

1、点赞服务单元化:要陆续往服务单元化的方向迭代、演进。

 

2、点赞服务平台化:在目前的业务接入基础上增加迭代数据分库存储能力,做到服务、数据自定义隔离。

 

3、点赞业务形态探索:以社区为基础,继续探索通过点赞衍生的业务形态。

相关 [mysql 千亿 系统] 推荐:

MySQL扛不住?B站千亿级点赞系统服务架构设计

- -
为了在提供上述能力的前提下经受住流量、存储、容灾三大压力,点赞目前的系统实现方式如下:. 整个点赞服务的系统可以分为五个部分. 流量路由层(决定流量应该去往哪个机房). 业务网关层(统一鉴权、反黑灰产等统一流量筛选). 点赞服务(thumbup-service),提供统一的RPC接口. 点赞异步任务(thumbup-job).

mysql 权限系统

- - 数据库 - ITeye博客
mysql 权限系统控制一个用户是否能进行连接,以及连接后能够针对那些对象进行什么操作. mysql权限控制包含两个阶段. 2:检查用户是否具有所执行动作的权限. 本文实例,运行于 MySQL 5.0 及以上版本. MySQL 赋予用户权限命令的简单格式可概括为:. 一、grant 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利.

mysql系统变量专题学习

- - IT技术博客大学习
要深入研究mysql那首先对mysql的一些系统/扩展变量有一定的了解,因为这些变量不仅决定mysql一些配置信息,还影响了mysql的性能优化提升,其中包括安全、优化、并发、复制等等. 笔者上网查了一下,这些资料有限,以及官网的一个中文文档介绍的内容简短(不包括值域,作用域,有些变量压根没翻译只是给出值)所以想写篇文章,一来学习巩固一下mysql,二来方便以后查阅.

用sqoop进行mysql和hdfs系统间的数据互导

- - CSDN博客云计算推荐文章
sqoop 是apache下用于RDBMS和HDFS互相导数据的工具. 本文档是sqoop的使用实例,实现从mysql到hdfs互导数据,以及从Mysql导数据到HBase. 一、从HBase库中直接导出到mysql中. 一开始我想从HBase库中直接导出到mysql中. 在mysql中创建一个库和表.

Oracle、Db2、SqlServer、MySQL 数据库插入当前系统时间

- - CSDN博客推荐文章
例如有表table,table 中有两个字段:name 、makedate. 插入系统时间应为sysdate:. insert into table (name,makedate) values('测试',sysdate);. 插入系统时间应为current timestamp并且makedate数据类型为timestamp.

linux系统下实现MySQL主从热备份

- - CSDN博客数据库推荐文章
2.用来实现读写分离,缓解一个数据库的压力.         Mysql的主从复制至少是需要两个Mysql的服务,当然Mysql的服务是可以分布在不同的服务器上,也可以在一台服务器上启动多个服务.         如果想配置成为同一台上的话,注意安装的时候,选择两个不同的prefix=路径,同时开启服务器的时候,端口不能相同.

MYSQL优化之关闭文件系统日志

- - Linux - 操作系统 - ITeye博客
通常数据库系统在数据大量操作时,会产生很大的磁盘io,关闭linux各文件系统的日志功能可以提高数据库吞吐量. 1)查看文件系统是否开启日志功能了. tune2fs -l /dev/sda2 | grep 'has_journal' 如果返回结果中出现has_journal,则说明该文件系统开启了日志(jbd,也即 journaling block device).

ActiveMQ系统之——消息持久化到MySQL数据库中(二)

- - CSDN博客推荐文章
关于这一节的程序,需要使用到《 ActiveMQ系列之——安装、运行及事例代码(一)》中的示例代码. 本文主要介绍关于消息持久化的配置. ActiveMQ默认情况下是基于文件的存储,使用的是kahaDB,当然还有其它的持久化方式,例如LevelDB,这个是在5.8的版本中引入的,本文主要介绍数据库持久化,使用的数据库是MySQL,其它数据库类似.

MySQLMTOP 开源 MySQL 监控系统 2.1 已发布

- - 开源中国社区最新新闻
MySQLMTOP开源MySQL监控系统2.1已于2014年2月28日发布,这次更新的内容如下:. 1.添加主机时设置一个默认端口3306,无需重复输入. 2.验证表单提示完善(英文提示汉化). 4.图表功能完善-图表可按小时,按天分析. 5.python函数连接数据库函数增加超时参数. 6.数据库优化,索引重建,历史数据表改为分区表.

Mysql Tomcat C3p0 系统性能调优个人总结

- - CSDN博客数据库推荐文章
应用逻辑 就是用c3p0 到数据库查询数据并http返回Json数据. 1 调优前的最初的测试结果   JMeter test result. 这个数据是从程序的log 中打印出的 数据库select语句 中得出的结果(正确与否后面会有讨论). 2 经过IOD系统打印 SQL query 的执行时间 和 tomcat 每个request 的 响应时间,找出 系统瓶颈 是因为一个 select语句 使用了 in:.