背景司春峰
哔哩哔哩技术专家
负责B站对象存储、NoSQL、数据传输、数据库代理等方向的研发工作,致力于提供稳定可靠高性能的存储服务。
BLOB(binary large object)存储,通常也被称为对象存储(OSS, object storage service)。一般用来存储文件,如视频文件、音频文件等。目前,各个云计算厂商都对外提供对象存储服务,其中以亚马逊的S3系统最著名,S3系统也成为行业的事实标准。各个云计算厂商推出的对象存储服务,也纷纷兼容S3标准。
B站由于其内容的独特性(视频网站),对象存储也有着非常多的需求。下面我们会介绍B站的对象存储的设计与实现。为了便于大家理解,会采用由简单到复杂的过程进行。我们称这个对象存储系统为BOSS(Bilibili Object Storage Service)。目标13天精通超大规模分布式对象存储系统的架构与设计。
Day1先研读S3协议,我们会发现S3其实提供的接口非常简单,主要有PUT/GET/DEL/LIST等几种类型的接口(这里先忽略分段上传等接口)。各个接口对应的语义和term定义如下:
- bucketName:bucket的名称,可以理解为目录名
- objectName: 对象名称,即文件名
- PUT: 以 bucketName objectName 作为key(主键),上传数据(比如一段视频)
- GET: 以 bucketName objectName 为key,下载数据(比如刚刚上传的视频)
- DEL: 以 bucketName objectName 为key,把之前上传的视频进行删除
- LIST: 以bucketName和指定的前缀为过滤条件,列出符合条件的key。比如以bucketName为前缀,列出已经上传的文件名 列表(根据上面的例子,就是列出已经上传的视频文件名)
看到这里,假设我们有一个性能非常强大的SQL服务(比如mysql ORZ), 那么我们可以建一张表(比如表名为data_and_meta),然后将数据存入即可。
表结构
系统架构
此时我们的系统架构如下图所示
- 协议接入层(解析http请求,并转换为对MySQL的操作)
- 存储层(MySQL服务)
其中协议网关可以采用golang编写,解析S3协议,并转换为后端对MySQL服务的操作即可。至此,Day1的工作完成, 收工回家。
Day2第一天在设计表结构的时候,数据和元数据都堆在一起,相互有影响。今天我们将元数据和数据拆开来。新建两张表,meta表和data表。
meta和data分离的表结构
如上图所示,通过object_id将meta表和数据进行关联,object id为一个int64类型(先不考虑object_id哪里来的)
优点
- 元数据和数据进行了分离存储
- 可以实现数据和元数据的分别更新(可以预见,后面需要新增字段,满足不同需求)
- 甚至可是实现rename操作(当然S3没有这个需求)
问题
- 对于相对比较大的文件,性能有可见的问题(先不考虑分段上传)。假设上传一个100MB的文件,只能放在MySQL的一个字段里面, 需要继续优化
引入Block表
针对单个data字段中的数据太长的问题,我们继续拆分,改成3张表,如下图所示
- name表
- object表
- 数据表(多张)