性能文章>一篇文章告诉你对象存储底层的工作机制>

一篇文章告诉你对象存储底层的工作机制原创

1年前
413444

大家好,我是威哥,《RocketMQ技术内幕》、《RocketMQ实战》作者、RocketMQ社区首席布道师、极客时间《中间件核心技术与实战》专栏作者、中通快递基础架构资深架构师,越努力越幸运,唯有坚持不懈,与大家共勉。

1、MinIO集群拓扑结构

MinIO可以部署到三种类型的拓扑:

  • Single Node Single Drive 一个Server节点,并且一个磁盘驱动器或者一个文件夹。例如,在本地PC上使用计算机硬盘驱动器上的文件夹进行测试。

  • Single Node Multi Drive

    单Server节点,多磁盘驱动器或多个文件夹。

  • Multi Node Multi Drive 多Server节点,多磁盘驱动器或多个文件夹。

2、分布式MinIO如何工作

2.1 MinIO如何管理多个虚拟机或物理节点

Server Pool由多个Minio服务节点与其附属的多个磁盘构成。MinIO支持向现有MinIO集群中增加一个或多个Server Pool,从而实现水平扩容。

当MinIO中有多个可用的Server Pool时,单个对象总是写入其中的一个Server Pool,如果一个Server Pool发生故障,并不会影响其他Server Pool的读写。

minio server命令中通过指定HOSTNAME参数来表示一个Server Pool,下面的命令表示创建一个单独的Server Pool,包含4个minio服务器节点,每一个服务器节点拥有4个驱动器(磁盘),总共16块盘。

00

其中hostname分别为minio1.example.net、minio2.example.net、minio3.example.net、minio4.example.net。

2.2 如何将多个Server Pool组合成一个MinIO集群

minio server命令可以指定一个或多个Server Pool,这样就多个Server Pool就构成了一个逻辑MinIO集群,例如下面的命令,会创建2个Server Pool。

minio server https://minio{1...4}.example.net/mnt/disk{1...4} \
             https://minio{5...8}.example.net/mnt/disk{1...4}

在一个MinIO集群中总是会将一个对象的多个版本存储在同一个Server Pool中,MinIO强烈建议生产集群一个Server Pool中至少包含4个MinIO服务器节点,以保证适当的高可用性和持久性。

2.3 MinIO集群水平伸缩

MinIO分布式集群支持扩缩容功能,以增加或减少可用存储。

水平扩容:支持向现有MinIO集群中添加一个或多个Server Pool,已增加集群整体资源,Server Pool内部的节点数一旦创建则无法修改。

水平缩容:对于拥有多个Server Pool的集群,我们可以使用decommission命令启动Server Pool的下线流程。温馨提示:一旦执行该操作,就无法停止,后续也无法再进行读写。请慎重处理。

2.3 如何管理MinIO集群

目前我们可以通过如下几种方式来管理MinIO集群:

  • 使用命令行工具:mc 和 mc admin
  • 使用MinIO官方提供的MinIO Console图形化界面
  • K8s集群环境中可以 MinIO Operator Console图形化界面

2.4 如何管理对象分布

MinIO不会将对象从旧的Server Pool中自动迁移到新添加的Server Pool中,即不会进行重平衡。但是,MinIO根据存储空闲大小进行加权选择,空闲空间越大的Server Pool会承担更多的写入流量,加权值是Server Pool的空闲空间量除以所有可用池上的空闲空间。

MinIO客户端版本从RELEASE.2022-11-07T23-47-39Z开始,你可以使用mc admin rebalance手动启动一个跨所有Server Pool的重平衡操作。

重新平衡不会阻塞正在进行的操作,但可能会导致业务的读写的性能降低。可以考虑在业务非高峰时段执行重平衡操作,而且你可以在任何时候可以停止或再次开启重平衡。

3、对象上传特性

MinIO完全实现了S3协议,你可以使用任何兼容S3协议的客户端,执行PUT操作将对象存储到MinIO集群。MinIO还实现了将一个对象拆分成多个部分后上传,MinIO会重新组装这些信息,直到拥有一个完整的对象后再存储在集群中。

4、MinIO高可用性设计

4.1 纠删码(Erasure Coding)

MinIO数据高可用性、可靠性和冗余性高度依赖纠删码。

MinIO纠删码是一种数据冗余和可用性特性,能够容忍部分磁盘损坏的情况下自动修复对象。Erasure Coding提供对象级的修复,与邻近的技术(如RAID或副本)相比开销要小得多。

纠删集(erasure set)是一组支持纠删码的多个驱动器集合。

MinIO会将每个对象分割为数据块和校验块,其中校验块支持重建丢失或损坏的数据块。MinIO将这些块写入到一个纠删集(erasure set)中。因此,MinIO可以容忍在部署中丢失多个驱动器或节点,具体取决于配置的奇偶校验和部署拓扑结构。

MinIO最高的冗余级别,MinIO可以损失将近一半(N/2 -1)的磁盘情况下还能继续提供读写服务,并且数据不会损坏。

MinIO默认为每一个对象设置4个校验块,即可以允许每一个纠删集(erasure set)丢失4块磁盘。

4.2 Erasure Sets(纠删集)

Erasure Set(纠删集)是一组磁盘组成,MinIO将纠删码的对象分块写入到其中。MinIO将一个对象的数据块、校验块随机均匀的分布在纠删集的不同磁盘上,同一个对象的同一种类型块在纠删集中同一个磁盘上只会出现一次,即不会有一个对象的两个数据块或校验块出现在纠删集中同一块磁盘中。

MinIO根据Server Pool中节点和驱动器的总数自动计算Erasure Sets的数量和大小(stripe size),其中最小stripe size为2,最大stripe size为16。stripe size选择算法考虑了部署中的节点总数,使得选中的stripe允许纠删集中驱动器均匀分布在池中的所有节点上。

Erasure set stripe size表示部署的最大奇偶校验值。

4.3 Erasure Code Parity (EC:N)

MinIO使用Reed-Solomon算法根据Erasure Set大小将对象分割为数据块和校验块。对于磁盘大小为M块的给定Erasure Set,MinIO将对象分割为N个校验块和M-N个数据块,MinIO集群默认的EC:N为EC:4,表示每一个对象的校验块为4个。

MinIO可以容忍每个Erasure Sets最多N个驱动器的损失,并继续执行读写操作(“仲裁”)。如果N恰好等于擦除集中驱动器的1/2,MinIO写至少需要N + 1块驱动器以避免数据不一致(“裂脑”)。

为部署设置EC:N是在可用性和总可用存储之间取得平衡。较高的EC:N以可用存储为代价提高驱动器或节点故障的弹性,而较低的EC:N提供最大的存储空间,降低驱动器/节点故障的容忍度。

下表列出了由1个节点和16块1TB驱动器组成的MinIO集群中不同erasure code Parity(EC:N) 的情况,如下图所示:

EC:N 数据盘最大可用容量 磁盘利用率 读请求最少需要可用磁盘数 写请求最小需要可用磁盘数
EC:4 12TB 0.750 12 12
EC:6 10TB 0.625 10 10
EC:8 8TB 0.500 8 9

4.4 Storage Classes (存储类)

MinIO通过Erasure Coding支持冗余存储类,允许应用程序为每个对象指定EC:N。

用于Erasure Coding的MinIO storage classes与用于分层的Amazon Web Services存储类不同。MinIO Erasure Coding存储类定义每个对象的奇偶校验设置,而AWS存储类定义每个对象的存储层。

MinIO提供了STANDARD、REDUCED_REDUNDANCY两个存储类,接下来分别介绍。

4.4.1 STANDARD

STANDARD存储类是所有对象的默认类。MinIO根据Erasure Set中的volumes(卷)数量设置STANDARD奇偶校验:

Erasure Set Size Default Parity (EC:N)
5 or Fewer EC:2
6 - 7 EC:3
8 or more EC:4

我们可以通过如下两种方式覆盖默认的奇偶校验:

  • 设置环境变量MINIO_STORAGE_CLASS_STANDARD的值
  • 使用mc admin config命令修改storage_class。

storage_class的EC:N最大值为Erasure Sets中EC:N的一半,最小为2。

STANDARD奇偶校验必须大于或等于REDUCED_REDUNDANCY。如果未设置REDUCED_REDUNDANCY,则STANDARD奇偶校验必须大于2。

4.4.2 REDUCED_REDUNDANCY

REDUCED_REDUNDANCY允许创建奇偶校验值低于STANDARD的对象。如果要设置为REDUCED_REDUNDANCY类型,MinIO集群中必须需要5个驱动器盘。

MinIO默认将REDUCED_REDUNDANCY奇偶校验设置为EC:2。您可以使用以下任何一种方法覆盖REDUCED_REDUNDANCY存储类奇偶校验:

  • 通过设置MINIO_STORAGE_CLASS_RRS环境变量的值
  • 使用mc admin config命令修改storage_class。

REDUCED_REDUNDANCY奇偶校验必须小于或等于STANDARD。

MinIO根据请求头中的x-amz-storage-class的值来确定讲对象分配给哪个存储类,设置x-amz-storage-class请求头方法有多重方式:

  • 对于mc命令行工具,某些命令包含用于设置存储类的特定选项,例如mc cp命令就具有storage-class选项,用于指定要对象的存储类型。
  • 对于MinIO sdk, S3Client对象有特定的方法来设置请求头。例如,mini -go SDK S3Client。PutObject方法以PutObjectOptions数据结构作为参数。PutObjectOptions数据结构包括StorageClass选项,用于指定要分配给正在创建的对象的存储类。

4.5 位损坏修复机制

位损坏是随机的、无声的数据损坏,可以发生在任何存储设备上。Bit rot损坏不会主动给用户提示,甚至操作系统也不会主动感知到数据已损坏。

MinIO使用哈希算法来确认对象的完整性。如果一个对象因比特位损坏,MinIO会根据纠删码自动修复对象。

4.6通过仲裁实现数据读写

在MinIO中执行任务必须有可用的最小驱动数,读写分别有各自的要求。MinIO需要更多的可用驱动器来维护写对象的能力,而不是读对象所需的驱动器,这个取决于EC:N的值,这块可以参考4.3中的表格加以理想,读写需要不同的驱动器数主要是当损坏的磁盘数量占据一半时,写需要超过一半数量才能正确写。

 

点赞收藏
丁威
请先登录,查看4条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

Redis stream 用做消息队列完美吗?

Redis stream 用做消息队列完美吗?

Netty源码解析:writeAndFlush

Netty源码解析:writeAndFlush

4
4