卷管理
创建
为用户创建卷,并分配一组数据分片和元数据分片. 在创建新卷时,默认分配10个数据分片和3个元数据分片。 UDB-TO以 Owner参数作为用户ID。
在创建卷时,如果集群中没有与该卷的Owner同名的用户时,会自动创建一个用户ID为Owner的用户
如果集群中已存在用户ID为Owner的用户,则会自动将该卷的所有权归属于该用户。
curl -v "http://192.168.2.160:15010/admin/createVol?name=vol1&capacity=10&owner=vol1&mpCount=3"
参数说明
| 参数 | 类型 | 描述 | 必需 | 默认值 |
|---|---|---|---|---|
| name | string | 卷名称 | 是 | 无 |
| volType | int | 卷类型:0-副本卷,1-纠删码卷 | 否 | 0 |
| capacity | int | 卷的配额,单位是GB | 是 | 无 |
| owner | string | 卷的所有者,同时也是用户 ID | 是 | 无 |
| mpCount | int | 初始化元数据分片个数 | 否 | 3 |
| dpCount | int | 初始化数据分片个数 | 否 | 默认10, 最大值200 |
| replicaNum | int | 副本数 | 否 | 副本卷默认3(支持1,3),纠删码卷默认1(支持1-16个) |
| dpSize | int | 数据分片大小上限,单位 GB | 否 | 120 |
| enablePosixAcl | bool | 是否配置 posix 权限限制 | 否 | false |
| followerRead | bool | 允许从 follower 读取数据,纠删码卷默认 true | 否 | false |
| crossZone | bool | 是否跨区域,如设为 true,则不能设置 zoneName 参数 | 否 | false |
| normalZonesFirst | bool | 是否优先写普通域 | 否 | false |
| zoneName | string | 指定区域 | 否 | 如果 crossZone 设为 false,则默认值为 default |
| ebsBlkSize | int | 每个块的大小,单位 byte | 否 | 默认8M |
响应示例
{"code":0,"msg":"success","data":"create vol[vol1] successfully, has allocate [10] data partitions"}
删除
首先把卷标记为逻辑删除(status设为1),然后通过周期性任务删除所有数据分片和元数据分片,最终从持久化存储中删除。 注意 纠删码卷使用大小为0时才能删除 在删除卷的同时,将会在所有用户的信息中删除与该卷有关的权限信息。
计算卷所有者 vol1的MD5值,方法如下:
echo -n "vol1" | openssl dgst -md5 执行此命令计算vol1的MD5值
(stdin)= 2b0d59c7031769e80c8e5118b6ec7694 得到MD5值
Restful API删除卷
curl -v "http://192.168.2.160:15010/vol/delete?name=vol1&authKey=2b0d59c7031769e80c8e5118b6ec7694"
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| authKey | string | 计算 vol 的所有者字段的32位 MD5 值作为认证信息 |
响应示例
{"code":0,"msg":"success","data":"delete vol[vol1] successfully,from[192.168.2.160:36664]"}
查询卷详细信息
展示卷的基本信息,包括卷的名字、所有的数据分片和元数据分片信息等。
curl -v "http://192.168.2.160:15010/admin/getVol?name=vol1" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
响应示例
{
"Authenticate": false,
"Capacity": 10,
"CreateTime": "2022-03-31 16:08:31",
"CrossZone": false,
"DefaultPriority": false,
"DefaultZonePrior": false,
"DentryCount": 0,
"Description": "",
"DomainOn": false,
"DpCnt": 0,
"DpReplicaNum": 16,
"DpSelectorName": "",
"DpSelectorParm": "",
"FollowerRead": true,
"ID": 706,
"InodeCount": 1,
"MaxMetaPartitionID": 2319,
"MpCnt": 3,
"MpReplicaNum": 3,
"Name": "abc",
"NeedToLowerReplica": false,
"ObjBlockSize": 8388608,
"Owner": "udbto",
"PreloadCapacity": 0,
"RwDpCnt": 0,
"Status": 0,
"VolType": 1,
"ZoneName": "default"
}
查询卷数据分片详细信息
展示卷的所有的数据分片信息
curl -v "http://192.168.2.160:15010/client/partitions?name=vol1" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
响应示例
{
"Epoch": 0,
"Hosts": [
"192.168.0.34:15310",
"192.168.0.33:157310",
"192.168.0.32:15310"
],
"IsRecover": false,
"LeaderAddr": "192.168.0.33:15310",
"PartitionID": 4,
"ReplicaNum": 3,
"Status": 2
}
查询卷元数据分片详细信息
展示卷的所有的元数据分片信息
curl -v "http://192.168.2.160:15010/client/metaPartitions?name=vol1" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
响应示例
{
"DentryCount": 1,
"End": 16777216,
"InodeCount": 1,
"IsRecover": false,
"LeaderAddr": "192.168.0.23:15210",
"MaxInodeID": 3,
"Members": [
"192.168.0.22:15210",
"192.168.0.23:15210",
"192.168.0.24:15210"
],
"PartitionID": 1,
"Start": 0,
"Status": 2
}
卷启用/关闭回收站
UDB-TO 的卷默认没有开启回收站功能。可通过 master 服务接口开启卷的回收站功能:
curl -v "http://192.168.2.160:15010/vol/setTrashInterval?name=udbtovol&authKey=126537c029fde6ef45ff6c39eabf1ca3&trashInterval=7200" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| authKey | string | volume owner字符串的MD5值。 |
| trashInterval | string | 回收站清理被删除文件的周期,单位分钟。默认0为不开启回收站功能。 |
响应示例
{
"code": 0,
"data": "update vol[udbtovol] TrashInterval to 7200 successfully\n",
"msg": "success"
}
开启回收站功能后,当第一次删除文件时,客户端会在挂载点的根目录下创建一个名为 .Trash 的隐藏文件夹。.Trash 内的 Current 文件夹内保留了当前被误删的文件/文件夹以及其完整的文件路径。Current 文件夹会定期被重命名为 Expired_过期时间戳 的文件夹。当 Expired 文件夹的过期时间戳到期时,则会删除该文件夹下的所有内容。
恢复误删文件
如前所述,只需要在 .Trash 文件夹下的 Current 或者 Expired 目录中找到被误删除的文件,即可根据其完整的父目录路径,将被误删的文件/文件夹通过 mv 操作恢复到被删除的原始位置。
清理回收站内的文件
需要注意的是回收站的内容依赖客户端的后台协程定期删除,因此如没有回收站对应卷的客户端在线时,回收站的内容会一直保留直到有回收站对应卷的客户端在线。 为了尽快的释放回收站的使用空间,也可以通过客户端直接对 .Trash 文件夹执行 rm 操作。
统计
展示卷的总空间大小、已使用空间大小及是否开启读写 token 控制的信息。
curl -v http://192.168.2.160:15010/client/volStat?name=vol1
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| version | int | 卷版本:0-副本卷,1-ec-卷。默认0-副本卷,访问纠删码卷必填 |
响应示例
{
"CacheTotalSize": 0,
"CacheUsedRatio": "",
"CacheUsedSize": 0,
"EnableToken": false,
"InodeCount": 1,
"Name": "abc-test",
"TotalSize": 10737418240,
"UsedRatio": "0.00",
"UsedSize": 0
}
更新卷参数
增加卷的配额,也可调整其它相关参数。
curl -v "http://192.168.2.160:15010/vol/update?name=udbtovol&capacity=10&authKey=126537c029fde6ef45ff6c39eabf1ca3" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| description | string | 卷描述信息 |
| authKey | string | 计算vol的所有者字段的32位MD5值作为认证信息 |
| capacity | int | 更新卷的datanode容量,单位G, 副本卷不能小于已使用容量 |
| zoneName | string | 更新后所在区域,若不设置将被更新至default区域 |
| followerRead | bool | 允许从follower读取数据,若设置为true,客户端也需配置该字段为true |
| enablePosixAcl | bool | 是否配置posix权限限制 |
| emptyCacheRule | string | 是否置空cacheRule |
| cacheRuleKey | string | 缓存规则,纠删码卷使用,满足对应规则的才缓存 |
| ebsBlkSize | int | 纠删码卷的每个块的大小 |
| cacheCap | int | 纠删码卷使用二级cache时,cache的容量大小 |
| cacheAction | in | 纠删码卷使用,0:不写cache, 1-读数据写cache, 2-读写数据都写到cache |
| cacheThreshold | int | 缓存文件大小限制,纠删码卷小于该值时,才会写到cache当中 |
| cacheTTL | int | 缓存过期时间,单位天 |
| cacheHighWater | int | 淘汰高水位 |
| cacheLowWater | int | 缓存淘汰低水位 |
| cacheLRUInterval | int | 缓存检测周期,单位分钟 |
响应示例
{
"code": 0,
"data": "update vol[udbtovol] successfully",
"msg": "success"
}
获取卷列表
curl -v "http://192.168.2.160:15010/vol/list?keywords=vol1" | python -m json.tool
获取全部卷的列表信息,可按关键字过滤。
参数说明
| 参数 | 类型 | 描述 | 必需 |
|---|---|---|---|
| keywords | string | 获取卷名包含此关键字的卷信息 | 否 |
响应示例
{
"code": 0,
"data": [
{
"CreateTime": 1757574885,
"DpReadOnlyWhenVolFull": false,
"Name": "vol1",
"Owner": "vol1",
"Status": 0,
"TotalSize": 10737418240,
"UsedSize": 0
}
],
"msg": "success"
}
卷扩容
对指定卷进行扩容到指定容量。
curl -v "http://127.0.0.1:15010/vol/expand?name=udbtovol&capacity=50&authKey=126537c029fde6ef45ff6c39eabf1ca3" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| authKey | string | 计算vol的所有者字段的32位MD5值作为认证信息 |
| capacity | int | 扩充后卷的配额,单位是GB |
响应示例
{
"code": 0,
"data": "update vol[udbtovol] successfully\n",
"msg": "success"
}
卷缩容
对指定卷进行缩小到指定容量。
curl -v "http://127.0.0.1:15010/vol/shrink?name=udbtovol&capacity=10&authKey=126537c029fde6ef45ff6c39eabf1ca3" | python -m json.tool
参数说明
| 参数 | 类型 | 描述 |
|---|---|---|
| name | string | 卷名称 |
| authKey | string | 计算vol的所有者字段的32位MD5值作为认证信息 |
| capacity | int | 压缩后卷的配额,单位是GB |
响应示例
{
"code": 0,
"data": "update vol[udbtovol] successfully\n",
"msg": "success"
}
两副本卷
主要事项
两个副本可以正常支持修改和写入(使用其他 dp 及其范围)
支持已创建的3副本卷设置2副本,并在创建新 dp 生效,但不包括老的 dp。
两副本卷有一个副本崩溃然后没有 leader 的情况下,使用
raftForceDel参数删除异常副本。
异常场景处理
例如存在一个 data partition,有两个副本A、B
两副本迁移的异常场景
迁移目标是C,我们实现的过程是先添加副本C,然后删除源A,迁移过程B crash。解决方式: 如果 B crash了,raft 不可用,先删除B,等待迁移完成,删除A,再添加一个副本
正常运营过程某一个副本crash,例如B
没有 leader,根据 raft 规则两副本不能删除B的,因为需要先 commit,然后 apply,但 commit 的条件是大多数存活。解决方式: 强制删除B
警告:raft 支持新接口 del,replica 直接不使用 raft log commit(先备份dp数据)
curl "http://127.0.0.1:15010/dataReplica/delete?raftForceDel=true&addr=127.0.0.1:15310&id=47128
addr 为副本B的地址
id 为分区id(
dpid)raftForceDel 强制删除 raft 副本
DataNode 将检查副本数(volume 和 dp 必须都是 2 个副本,以防使用不当)和 force 字段。
命令行
两副本卷的创建
curl -v "http://192.168.2.160:15010/admin/createVol?name=udbtovol&capacity=100&owner=udbtovol&mpCount=3&replicaNum=2&followerRead=true"
原有三副本卷降为两副本
存量的数据只读(建议批量脚本执行)
curl -v "http://192.168.2.150:15010/admin/setDpRdOnly?id=**&rdOnly=true"
更新卷副本数量,更新后3副本分区会异步降低为2副本
curl -v "http://192.168.2.160:15010/vol/update?name=udbtovol&replicaNum=2&followerRead=true&authKey=126537c029fde6ef45ff6c39eabf1ca3"
强制删除(无 leader 情况下使用,注意:确定删除副本已经不可用)
curl "192.168.2.160:15010/dataReplica/delete?raftForceDel=true&addr=192.168.2.160:15310&id=47128"
流控
主要事项
考虑到不区分 volume 的存储组件,在 client 端做 volume 限流
分布式场景,需要中心控制 client 端流量,master 做中心,保证 iops,不增加额外流控 server,可以减少运维压力
client 采用幂函数控制流量增长,在流量在资源充足的场景下,可以快速增长
保证 volume 整体流量调控下平稳
master 可以均衡客户端流量,根据客户端请求情况自适应调节
配置项
无配置项,通过url命令设置
QOS流控参数及接口
创建卷时启用QOS
# 启用qos,写流量设置为10000MB
curl -v "http://127.0.0.1:15010/admin/createVol?name=qoslimitvol&capacity=100&owner=udbtovol&qosEnable=true&flowWKey=10000"
响应示例
{"code":0,"msg":"success","data":"create vol[qoslimitvol] successfully, has allocate [10] data partitions"}
获取卷的流量情况
curl "http://127.0.0.1:15010/qos/getStatus?name=qoslimitvol" | python -m json.tool
响应示例
{
"code": 0,
"data": {
"ClientALiveCnt": 0,
"ClientHitTriggerCnt": 1,
"ClientReqPeriod": 1,
"ClusterMaxUploadCnt": 20000,
"QosEnable": true,
"ServerFactorLimitMap": {
"3": {
"Allocated": 0,
"Buffer": 34359738368,
"CliNeed": 0,
"CliUsed": 0,
"LastMagnify": 0,
"LimitRate": 0,
"Name": "FlowRead",
"NeedAfterAlloc": 0,
"Total": 34359738368,
"Type": 3
},
"4": {
"Allocated": 0,
"Buffer": 10485760000,
"CliNeed": 0,
"CliUsed": 0,
"LastMagnify": 0,
"LimitRate": 0,
"Name": "FlowWrite",
"NeedAfterAlloc": 0,
"Total": 10485760000,
"Type": 4
}
}
},
"msg": "success"
}
获取客户端数据
curl "http://127.0.0.1:15010/qos/getClientsInfo?name=qoslimitvol" | python -m json.tool
响应示例
{
"code": 1,
"data": null,
"msg": "not found"
}
更新服务端参数,关闭、启用流控,调节读写流量值
curl "http://127.0.0.1:15010/qos/update?name=qoslimitvol&qosEnable=true&flowWKey=100000"| python -m json.tool
响应示例
{
"code": 0,
"data": "success",
"msg": "success"
}
一些系统参数说明
默认单位
无论是 client 端还是 datanode 端,目前流量都是 MB 为单位
最低参数流量和 io,作用于 datanode 和 volume 的设置,如果设置值,则需要保证一下要求,否则报错
MinFlowLimit = 100 * util.MBMinIoLimit = 100
如果没有设置流量值,但启用限流,则使用默认值(Byte)
defaultIopsRLimit uint64 = 1 << 16defaultIopsWLimit uint64 = 1 << 16defaultFlowWLimit uint64 = 1 << 35defaultFlowRLimit uint64 = 1 << 35
Client 和 Master通信
Client 长时间收不到 Master 的流量控制,日志会 warn 出来
Client 和 Master 无法不通讯,会维持原有流量限制,也会 warn 出来
流量长时间为 0 则不会主动请求 Master 流量,不上报给 Master,减少通信请求。Master 会清理长时间不上报客户端信息。
冷卷
读一级缓存不算作流量
cache 写不计入写流量控制
其他都算作流量