本文根据王志广老师在〖deeplus直播:分布式数据库转型与运维实践探讨〗线上分享演讲内容整理而成。
王志广
bilibili 基础架构数据库负责人
- 十年以上数据库运维经验,曾在多家大型互联网公司任职,主导和参与了多家数据库私有云建设、数据库多活、数据库架构从商业数据库到开源数据库的迁移。2020年加入B站,主导了B站新一代数据库可用系统BRM、MongoDB私有云等项目。目前主要专注于B站数据库多活、数据库服务治理等。
分享概要
一、业务场景
二、架构演进
三、架构设计
四、稳定性
五、效率
一、业务场景
在开始讲解之前,我先为大家介绍一下B站的业务场景。B站的业务大体上可以分为以下几类:
1、点播类业务
点播类业务就是大家经常看的视频以及稿件之类相关的业务,这类数据使用场景的特点有:
- 数据一致性要求较高
- 耗时敏感
- 流量大
- 可用性要求高
2、直播类业务
直播类业务对应B站的S12、跨晚、拜年祭等,有以下几个特点:
- 数据一致性要求较高
- 热点数据,如S12的主播房间
- 平时流量中等,大型直播流量会呈现爆炸性增长
- 可用性要求高
3、游戏类业务
- 数据一致性要求较高
- 耗时敏感
- 流量大
- 可用性要求高
4、电商类业务
如B站本身的会员购,这类业务的要求如下:
- 数据一致性要求较高
- 热点数据,集中在秒杀场景及热门番剧
- 平时流量中等,热门番剧及商品会呈现爆炸性增长
- 可用性要求高
5、支付类业务
- 数据一致性要求极高
- 可用性要求高
- 流量不大
二、架构演进
介绍完B站的业务场景之后,接下来是B站整体数据库的架构演进历史。
1、1.0阶段
1.0阶段对于所有互联网公司而言,其实都有类似的架构——简单的主从,所有流量集中在一个主库上。另外,与以前使用的商业数据库类似场景——单实例多库。这种架构在公司刚起步的时候是比较方便的,便于业务的快速迭代,但是随着流量的增长,会出现以下几个问题:
1)单机的性能瓶颈
服务器的CPU、内存、存储的限制我们不可能一直垂直升级,从而出现了我们第一个架构演进的小版本——读写分离和一主多从,此场景有两个核心要求:
- 数据一致性要求较低
- 数据敏感度要求较低
满足以上两个要求的场景可以很好地规避因MySQL主从复制存在的延迟所带来的问题,同时又可以满足业务快速增长带来的流量压力。
2)各业务互相影响
随着业务的发展,各个业务之间的互相影响推动了我们架构的第二个小版本出现——按照业务库进行迁移拆分。
基于读写分离和业务库维度的拆分还是无法避免各个功能模块的互相影响。在这种情况下,架构1.0阶段的第三个小版本应运而生——基于业务的功能维度进行拆分,将一个X库拆分为n个库,拆分完之后分布在不同的实例。在每个不同的实例下,我们会有不同数量的从库支撑业务的流量增长,以满足大部分场景的业务需求。现在B站也有很多业务采用类似的架构,通过进行垂直业务拆分满足我们的业务增长。
2、2.0阶段
架构2.0阶段——水平拆分。成熟、稳定、定制的Proxy是水平拆分的利器,而一个符合要求的Proxy是需要时间进行打磨。为满足业务的快速发展,我们选择在业务层实现,也就是我们在代码层实现路由,虽然配置时会比较繁琐,但能够满足大部分业务场景,很多互联网公司也有类似的阶段。在业务侧进行水平拆分之后,我们其实面临着一个新的问题——跨实例查询。
3、3.0阶段
1)第一个阶段
进入B站演进的3.0阶段,我们引入了TiDB,将之前业务层面的分片数据通过TiDB本身的DTS同步到TiDB集群,从而满足了大部分业务的查询需求。同时我们在部分场景的业务下直接尝试使用TiDB。
引入TiDB之后,基于B站的特点,我们对其进行了本地化定制。由于TiDB Server是无状态的,而官方对于如何路由到每个节点也没有一个通用的解决方案。因此我们结合 B站的基础平台能力,将TiDB Server全部在PaaS上进行容器化,同时把我们的服务发现能力和TiDB Server进行整合,并对相应语言的SDK进行改造,从而实现了TiDB Server的负载均衡,解决了TiDB Server本身的瓶颈,如:故障切换、业务快速感知节点变化、连接数等。
2)第二个阶段
到了3.0的第二个阶段,我们已经把Proxy打磨为一个很成熟的产品,同时为满足支撑了异地多活的场景,我们还定制了DTS,把我们数据库的部署从同城多活直接做到了异地多活,也就是两地三中心的架构。
首先,在DTS方面,我们也基于B站本身技术栈的特点做了大量的定制,与其它公司开源的组件有部分不同。例如冲突检测,我们提供了多种可选择的规则,包括基于特定字段的以及全字段匹配的,同时对于冲突字段数据的R数据处理,我们一般会有两种途径:
- 一是直接冲突的场景,将不重要的数据直接打入到我们的队列里,也就是我们公司之前的Data Bus里;
- 二是业务方可以基于打到Data Bus里的数据做冲突数据处理,通过DTS提供一个接口将数据回写到特定的机房,因为当需要把数据重新写入数据库时,也是需要做防回环的处理,所以我们DTS上提供一个接口供业务使用。
其次,在主从切换的时候,由于两地三中心要保证数据可以进行来回切换,切换期间虽然是全局进行,但是一些边缘场景下仍然会存在数据冲突的问题。所以我们也提供了一个在主从切换下数据冲突以及相关信息的打捞队列,实现二次处理的功能,这也是我们中间 DTS提供的一个能力。
Proxy的能力与各家主流的功能是类似的,都能够支持读写分离、分库分表、限流、黑白名单等。对于Proxy的部署,我们采取了两种方案:
- 一是集中式部署,类似于大家常说的网关模式,能够便捷地进行统一的限流及资源的调控;
- 二是Sidecar模式,应用层在使用方面比较简单,直接配置本地IP即可,但是同时已带来其他问题,如全局的管控(限流、连接等)、成本等。