头图

前言

为了满足业务的需求,信也科技基于SeaweedFS搭建了分布式文件存储服务,目前已在生产环境落地,陆续接入了部分业务场景,积累了一些经验。本人也在参与该项目的过程中也对SeaweedFS源码进行了深入研究,下面将会给大家分享SeaweedFS Volume节点数据存储设计,也会对其核心源码进行解读。

Volume数据节点介绍

之前已经对SeaweedFS集群和Master节点进行了讲解,所以这里不再重复,如果有对相关概念不了解的同学请看这几篇文章:分布式文件存储SeaweedFS简介与Mount功能原理解密SeaweedFS Master节点Raft协议源码解析

Volume节点的职责


SeaweedFS是一个分布式文件存储中间件,由Filer、Master、Volume三种节点组成集群。在文件上传流程中Filer节点负责将大文件切分成小的文件块(needle),Master节点会为每一个小文件块分配文件ID和存储位置(volume),Volume节点负责将文件块存入磁盘并维护索引。

基本概念

  • Volume节点:存储数据的节点。
  • Volume:数据节点管理文件的单元。本质是一个数据文件和一个索引文件。
  • Needle:表示一个文件块,存储在Volume的数据文件中。

Volume节点和Volume是两个比较容易混淆的概念:Volume节点是运行在服务器中的一个进程(对应代码中的VolumeServer结构体),Volume是Volume节点中为了方便管理文件而设计的结构体(对应代码中的Volume结构体)。在物理层面Volume就是两个文件:一个最大为30GB的数据文件,一个索引文件。用户上传的文件会封装为一个Needle然后以追加的方式写入数据文件中,并在索引文件中记录文件ID、起始Offset、文件Size,在下载时可以通过索引文件快速定位到Needle在数据文件中的位置。

  • Volume结构体

    数据存储设计

    通过上面的简单介绍,我们已经了解了文件在单个节点上是如何存储的,但在分布式系统中,数据必须具有备份、容灾能力,所以下面将介绍SeaweedFS中提供的两种数据备份方式:多副本、纠删码(EC)。

    多副本存储

    与其他存储中间件相同,SeaweedFS提供多副本数据存储能力。在启动Master节点时可以通过-defaultReplication=XYZ配置副本数,其中xyz分别代表:

  • X:在不同数据中心的副本数
  • Y:在相同数据中心不同机架的副本数
  • Z:在相同机架不同服务器的副本数

例如,我们在搭建集群时启动参数为-defaultReplication=020,代表在不同的机架额外维护两个副本,也就是总共存储三份数据。

多副本数据一致性

为了保障数据的一致性,需要满足公式 W + R > N,其中 W 代表写入几个副本才算写入成功,R 代表读取数据需要读取几个副本,N 代表数据总共有几个副本。在SeaweedFS的实现中 W = N、R = 1,也就是必须所有副本写入成功才认为写入成功,读取时只需要读任意副本即可。

  • 文件上传代码实现
  1. 根据Master节点分配的地址,选择一个Volume节点调用API写入文件数据。
  2. Volume节点接收到请求后先写入自身本地存储。
  3. 在根据备份策略查找备份节点,写入备份节点。
  4. 任意一个节点写入失败则返回失败。



    多副本高可用

根据上面的一致性公式 W = N,数据写入需要所有副本都写入成功,那是不是意味着只要有一个节点宕机就无法写入数据了呢?当然不是。下面我们将会介绍SeaweedFS在多副本模式下如何保证服务高可用。

  • 读高可用
    在多副本模式下,所有的Volume都会存储 N 个副本,副本会分散在多个 Volume 节点上,根据上面讲的一致性策略,读文件只需要读取一个副本,所以只要有一个副本存活就可以提供读服务。
  • 写高可用
  • Volume节点宕机会导致其上面的Volume变为只读状态。
  • 只读状态的Volume不会被Master节点分配写入请求。
  • 当没有足够的Volume可以写入时会触发扩容。

    如图,我们以3节点2副本举例,假设3号Volume节点宕机,那么Volume-2会被标记为只读状态。新的文件上传请求会被分配到Volume-1中,如果Volume-1也处于无法写入状态(比如写满了),那么会新建一个Volume-3并将新的文件写入Volume-3中。

纠删码存储(EC)

多副本存储会导致存储空间翻倍,空间利用率低,例如:三副本存储空间利用率为33%。纠删码存储可以在实现数据备份、容灾的前提下提高空间利用率,降低存储成本。在实现时根据计算纠删码的时机不同可以分为在线、离线两种方式:

  • 在线计算:每上传一个文件都实时计算纠删码。
  • 离线计算:先使用多副本存储文件,然后离线批量计算转换为纠删码存储。
    SeaweedFS在设计上主要是面向小文件存储,只实现了离线计算纠删码,所以下面只讨论离线纠删码。

纠删码是什么

纠删码存储会将原始数据切分为 N 个大小相同的数据块,然后通过计算的到 M 个相同大小的校验块,将 N + M 个块均匀的存储在多台服务器中,即可实现丢失任意 M 个块都可以通过逆向计算恢复数据。在SeaweedFS中使用RS(10, 4)算法,也就是将原始数据平均分为 10 个数据块,然后通过纠删码计算得到 4 个校验块,任意丢失 4 个块都可以通过逆向计算恢复数据。
RS(10, 4)算法只额外占用了40%的存储空间就可以容忍4个分区数据的丢失,空间利用率为70%,而多副本存储需要至少5个副本才能实现,空间利用率为20%。

SeaweedFS纠删码存储


SeaweedFS实现的是离线EC,也就是数据会先按照三副本的方式存储,通过定时任务的方式将存储空间达到95%(默认值为95)的Volume转换为EcVolume,计算过程如下:

  1. Volume筛选,筛选出容量超过95%也就是存储了超过28.5GB数据的Volume。
  2. 将筛选得到的Volume标记为只读状态。
  3. 选择任意一个节点上的副本进行纠删码计算,数据块和校验块都会暂时存储在该节点。
  4. 将数据块和校验块分发到其他节点(该步骤会占用较高网络带宽,不过可以进行限速)。
  5. 删除其他副本。

纠删码存储的一致性和高可用

在SeaweedFS设计中,纠删码存储的数据是不变的,所以不存在一致性问题,也不存在写操作高可用问题,只需要保证读高可用即可。上面其实也提到了,当节点宕机时可以通过计算实时恢复数据保证读高可用,所以接下来直接看代码。

  1. 先判断数据是否存储在当前节点,如果是则直接读取当前节点。
  2. 判断数据是否存储在其他节点,如果是则直接读取其他节点的数据。
  3. 上述两条都不成立则需要恢复数据。
    1) 从其他节点读取数据。
    2) 通过逆计算恢复数据。
    3) 返回数据所在分片。


    总结

本文简单介绍了Volume节点的设计,讲解了三副本存储和纠删码存储的一致性设计与高可用设计。但受篇幅所限,部分细节并没有过多的展开,例如:HayStack海量小文件存储设计、纠删码算法、在线纠删码、Volume状态维护等。我计划在后续的文章中逐步讲解,敬请期待。

作者简介

LGW 信也科技基础架构研发专家,主要负责分布式文件存储的研发工作


信也科技布道师
12 声望10 粉丝

引用和评论

0 条评论