前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RGW百亿级对象存储扩容方案

RGW百亿级对象存储扩容方案

作者头像
用户1260683
发布2019-12-26 14:01:01
2.1K0
发布2019-12-26 14:01:01
举报

现有扩容问题

  1. 元数据扩容: 1). 单个bucket存在object数量上限:受限于bucket的index shard数量,而shard数量存在上限。 2). 在线调整shard数量会对业务读写产生较大性能影响,并且调整时长无法预期,理论上object数量越多,reshard时间越长,随着object到达上亿级别,每次reshard时间都会越来越长同时还隐藏较大的元数据丢失风险。 3). 单个集群的元数据最终都存储在RocksDB中,需要考虑到随着object数量不断增加导致RocksDB实例过大的情况,大体积的DB实例一旦发生compaction会对底层性能和稳定性造成巨大影响。
  2. 数据扩容: 1). 单集群对data zone进行添加OSD方式进行扩容会导致数据重新平衡,当object数量在上亿规模的场景下,重新平衡的时间非常长且不可控,对业务影响较大。 2). 单集群就算业务能够忍受OSD的扩容影响,也会始终受限于单个集群的机柜数量限制:一个集群不可能在同一个机房无限制的新增存储节点。 3). 目前采用的跨集群扩容是基于bucket的Virtual hosted style访问去进行路由,业务需要根据容量使用情况不断的新增bucket去扩容,对业务来讲,多套代码环境还要同时维护多个bucket,开发和维护成本较高。
  3. 一致性哈希算法的扩容的弊端 一致性hash一旦发生节点扩容/缩容会导致数据重新平衡,虽然平衡导致的迁移数据量很小,但是一旦到达百亿级别的规模,迁移一次成本依然非常高。

用户需求

  1. 用户需要长期读写一个bucket,不接受以切换bucket方式去进行扩容。
  2. 接受客户端代码逻辑的轻量级改造,但是后端扩容期间客户端不允许停机。
  3. 后端扩容必须对客户端透明,并且将后端扩容对业务的影响降到最低。
  4. 客户端全部都是小文件读写,不会用到multipart upload方式去上传。
  5. 只有简单的读写object和object acl setting等几个简单操作,不会有bucket之间的object copy操作。
  6. 用户基本上都是新增数据,很少覆盖和修改已有数据的操作。
  7. 用户自己在数据库维护object列表,不需要在bucket内的list操作。

整体思路

依然采用一致性hash算法去进行扩容,但是对该算法进行了改进,收益在于:

  1. 支持后端节点的扩容,同时不会产生数据迁移
  2. 能够根据后端资源的使用率,灵活调整多个集群的负载,提高整体资源利用率。
  3. bucket/object的寻址不是通过遍历查找,而是通过hash计算,能够极大减少路由条目数和提高寻址效率。
方案思路

沿用现有的S3存储模型以及标准协议,将多个底层bucket(带权重)聚合成一个大的bigbucket,用户所有的操作都基于同一个bigbucket进行,不再需要进行bucket切换。

整体构架

新增一个Bugbucket Gateway进行路由和请求处理,将来自client端的请求根据hash路由规则转发到后端zone上面的bucket,之后再将后端的返回的请求内容返回给最终的客户端。

算法简介

数据访问需要在客户端的object名称之前新增一个{ringtoken}字段,同时将支持path和Virtual host两种方式。

将多个底层的bucket聚合成一个ring,形成一个资源分组,其中底层bucket名称仍然需要保持全局唯一。单个ring里面的bucket可以在同一个zone(如 Ring1和ring2),也可以跨越多个zone(如 Ring3)。同时每个Ring里面的bucket都按weight分配权重。这样灵活的组合能够最大程度的实现底层资源的灵活调度。

由一组ring形成一个周期环状的结构,每次扩容以ring为单位,比如第一轮新建一个集群,由bucket1~4 组成一个ring0,当经过一个时间周期(比如一个月),如果之前的ring0对应的bucket仍然有比较多的空间,可以新建一个ring1 指向同样的bucket1~4,实现底层资源的复用。之后如果之前分配的空间不足,可以依次新建ring2、ring3 指向新的bucket5~8,实现底层资源的扩容。

下图为,在Ring0分配的空间bucket2和bucket4还有剩余的情况下(比如剩余还有30%空间,分配权重为30),通过在另外一个集群新建bucket5和bucket6(分配权重100),组成一个新的ring1,实现跨集群资源的组合,到集群资源利用的最大化。

ringtoken的分发

整个算法在工程实践上需要解决的一个问题是如何确保客户端能够按照预期去更新对应的ringtoken,将最新的写入请求落到正确的后端所在bucket。目前有两种解决方案

方案1 服务端下发配置

客户端每次写入之前从网关处查询最新的ringtoken。(获取到ringtoken以后缓存到本地,并设置过期时间,发现过期以后再更新)

方案2 客户端/服务端 按约定规则进行循环

和客户端商定ringtoken的轮换规则,比如按一个月一次,12个月为一轮,如此往复。

代码语言:javascript
复制
#/usr/bin/python
import time
ringtoken={"01":"ring0",
           "02":"ring1",
           "03":"ring2",
           "04": "ring3",
           "05": "ring4",
           "06": "ring5",
           "07": "ring6",
           "08": "ring7",
           "09": "ring8",
           "10": "ring9",
           "11": "ring10",
           "12": "ring11"}

current_month =  time.strftime("%m", time.localtime())
current_ringtoken =  ringtoken[str(current_month)]
print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print current_ringtoken


output:
2019-05-22 16:37:55
ring4

数据处理流程

整个Bigbucket Gateway主要功能如下:

  1. 对访问bigbucket的request请求进行认证和鉴权。对应步骤1
  2. 根据客户端提交的ringtoken按指定好的hash算法进行路由,将请求转发到对应的集群bucket(按后端的认证要求,需要对request内容进行重新签名)。对应步骤2
  3. 等待后端处理,获取后端集群的Response。对应步骤3
  4. 修改后端的Response信息,返回最终结果给客户端。对应步骤4
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Ceph对象存储方案 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现有扩容问题
  • 用户需求
  • 整体思路
    • 方案思路
      • 整体构架
      • 算法简介
      • ringtoken的分发
        • 方案1 服务端下发配置
          • 方案2 客户端/服务端 按约定规则进行循环
          • 数据处理流程
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档