简介

minio多版本这个特性只有server模式才支持,gateway模式不支持。 本文解读的minio版本较旧,代码版本日期为2022/04/18,仅供参考

bucket versioning 属于一个子系统,初始化后能提供几个接口:

Enabled(bucket string)
Get(bucket string)
Suspended(bucket string)

其中接口的实现依赖另外一个子系统模块BucketMetadataSys

BucketMetadataSys系统记录了元数据,当获取元数据的时候,先从内存中(map结构)搜索相应的key是否找到数据,如果没有则从文件加载,meta文件路径为:buckets/{bucket}/.metadata.bin

GetBucketVersioning接口

file

代码实现:

  • checkAuth
  • checkBucketExist
  • 从bucket versioning 子系统根据桶名称获取配置,version系统依赖meta系统:
    • 元数据子系统BucketMetadataSys根据key从内存中加载, 内存有个map结构用于快速记录元数据,如果map中根据bucket 名能找到则快速返回meta数据,(bucket meta是个复合结构,其中version字段为[]byte)
    • 如果内存内找不到则加载相应bucket的元数据文件并反序列化得到数据后返回,数据结构同上

PutBucketVersioning接口

前提条件

  • bucket锁开启时不可用
  • bucket replication 开启时不可用

如图

file

实现步骤基本同GetBucketVersioning

  1. checkAuth
  2. checkIsLocked
  3. checkReplicated
  4. Bucket

DeleteObject接口(EC模式下的实现)

开始解读之前先回顾下

aws对s3接口DeleteObject的介绍

这部分是背景知识,可参考aws官网了解S3这个接口,这里简单复述下

启用版本控制后,对象被分配有versionID file

启用版本控制后,简单 DELETE 无法永久删除对象。S3 将在存储桶中插入删除标记,该删除标记将成为对象的当前版本并具有新的 ID。 file

于是简单的GET/HEAD因为DeleteMarker存在,直接返回:404 The specified key does not exist file

但是实际上,数据都还在桶内,只是分配了不同ID记录,因此通过指定version ID还是能找到 file

要永久删除受版本控制的对象,必须使用 DELETE Object versionId

下图显示删除指定的对象版本将永久删除该对象。 file

minio分布式+EC模式下的桶和对象处理

以下多盘+多服务节点的存储结构(3*3) 登陆任意一个节点 看到其中test-bucket有三个对象:

file

  • 可以看到桶内的对象都有相应的文件夹,且都有一个xl.meta 文件对应相应的元数据。
  • 实际数据的存储分情况: minio按照规则,比如对象大小、blockSize、dataBlockNum、parityBlockNum按照算法计算
  1. 当size比较小的对象,内容直接嵌入到元数据的二进制文件里面比如上图的allin1.yaml meta区外还包含了一部分数据,代码里称为这部分数据为内联数据 file

  2. 当对象比较大,minio会将池化处理,并放在所属的对象目录下 解码此对象的元数据xl.meta(为了方便分析,decode程序把加密的数据路径DDir也解码出来显示): 可以看到对象的元数据里面数据目录DDir字段指向了此对象的分段数据(part.1)的存放位置。(图示此时只有一个版本数据) file

当开启多版本后

这里也是要区分情况

  1. 对于小对象,仍然保存在mata里面作为内联数据(通过versionID区分)

    file 同时此对象的元数据xl.meta记录了两条记录(version): file

  2. 对于size大一点的对象则仍然使用会写到EC池,即单独目录下(其有可能是EC池中的多个set,meta中能索引到具体的数据目录,如下图,新版本较大后的存放)的part.N 解码新对象的元数据,也是记录了两个版本 如下图 file file

结论

多版本的实现,元数据会有版本记录,且能索引到数据位置(无论内联数据或者EC set)。 删除的时候只是添加delete marker,数据都还在,类似restic 快照的逻辑