带你读《存储漫谈:Ceph原理与实践》——3.2.5 元数据 / 数据同步

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 带你读《存储漫谈:Ceph原理与实践》——3.2.5 元数据 / 数据同步

3.2.5  元数据 / 数据同步

Ceph RGW 的多数据中心(Multisite)机制用于实现多个 Ceph 对象存储集群之间的元数据、数据同步。


1. 元数据同步

(1)多数据中心简介

Ceph 的多数据中心有如下几个概念:Realm、Zone Group、Zone,如图 3-31 所示。

image.png

图 3-31 多数据中心示意

每个 Realm 都为一个独立的命名空间,桶名在所在命名空间内是唯一的,即一旦在某个 Realm 下创建了桶 A,则 A 这个名字就被使用了,在该 Realm 下其他人就无法创建出名字为 A 的桶。

一个 Realm 下可以有多个 Zone Group。顾名思义,每个 Zone Group 可以对应多个Zone,即 Zone Group 是一组 Zone 的集合,Zone 之间同步数据和元数据。

通常一个 Zone 为多台服务器组成的一个 Ceph 集群,由一组 RGW 对外提供服务,一个集群上部署多个 RGW 网关,以对请求进行负载均衡。

在一个 Realm 下的多个 Zone Group 中,必须有一个 Master Zone Group,Master Zone Group 中必须有一个 Master Zone,在 Master Zone Group 下的 Master Zone 中执行用户的创建、删除、修改操作会记录一些日志信息(MDlog),这些日志信息被克隆到其他 Zone Group 下的 Zone 中,其他 Zone 中的 RGW 网关依照日志信息从 Master Zone Group 下的 Master Zone 中已配置的 endpoints 拉取元数据信息并执行相应操作。

在 Ceph 的配置中有以下几个参数与多数据中心机制相关,分别为 rgw_realm、rgw_zonegroup、rgw_zone。一旦设置好这 3 个参数并启动 RGW 网关,RGW 就会默认到 .rgw.root 下寻找相应的 Realm、Zone Group、Zone 信息,如果无法找到则启动失败。用户也

可 以 通 过 修 改 参 数 rgw_realm_root_pool、rgw_zonegroup_root_pool、rgw_zone_root_

pool 的配置值,来告诉 RGW 网关到指定的存储池下读取 Realm、Zone Group、Zone 等信息。

默认情况下,一个 Realm 下的不同 Zone Group 之间只会进行元数据同步,元数据包括用户信息、bucket、bucket.instance 信息。RGW 实例在启动时,会启动 RGWMetaSyncProcessorThread 线程进行多数据中心元数据的同步服务。

一个新的 Zone Group 加入已存在的 Realm 时,会执行全量同步,完成全量同步后就会进入增量同步阶段。在此阶段,新加入的 Zone Group 下的 Zone 内的 RGW 网关每隔 20s(通过 INCREMENTAL_INTERVAL 参数配置)到 Master Zone Group 中拉取日志信息 MDlog。

在增量同步阶段,每隔 20s 执行如下动作。

1)查询请求带上 marker 参数发送到 Master Zone Group,查询是否有新增的 MDlog,如果有,则拉取新增的 MDlog 到本地集群;

2)读取保存在本集群的新增的 MDlog 并处理,按照 MDlog 记录信息发送读取元数据请求到 Master Zone Group ;

3)保存从 Master Zone Group 读取到的元数据信息到本地集群;

4)更新 marker 参数。

(2)MDLog 简介

Mdlog 为 Master Zone Group 上的 RGW 网关记录,日志信息记录在 Log 池下的meta.log.PERIOD.SHARD_ID 对象的 OMAP 上,shard_id 默认为 0 ~ 31。

以下命令可查询第 0 个 shard 上的 omapkey,key 为 1_ 开头,后面带记录 Log 的时间戳。

#rados -p zgp2-z1.rgw.log listomapkeys meta.log.315d0473-9ff8-4828-83fd-96fdc
36ed618.01_1598684563.695864_0.1

也可以使用 radosgw-admin 命令查看 MDlog 日志信息的状态,状态信息中有 marker 和last_update 的时间信息,marker 记录上次同步的位置,last_update 记录上次同步的时间。

#radosgw-admin mdlog status
[
  {
    "marker": "1_1598768113.971442_11.1"
    "last_update": "2020-08-30 06:15:13.971442Z"
  }
]

status 信息保存在 Log 池下的 RADOS 对象中,可通过如下命令进行查询。

#rados -p zgp2-z1.rgw.log ls
mdlog.sync-status.shard.0
mdlog.sync-status

当主数据中心没有元数据更新记录到 MDlog 时,以下是从主数据中心拉取 MDlog 请求时没有新 MDlog 返回的请求和响应。

GET /admin/log?type=metadata&id=0&period=315d0473-9ff8-4828-83fd-
96fdc36ed618&max-entries=100&marker= 当前的 marker&rgwx-zonegroup=7085627f-27f8-
4779-9552-ebdd13c265e2 HTTP/1.1
HTTP/1.1 200 OK
Content-Length: 44
{
"marker": ""
"entries": []
"truncated": false
}

当主数据中心有元数据更新记录到 MDlog 时,以下是从主数据中心拉取 MDlog 请求时有新 MDlog 返回的请求和响应。

GET /admin/log?type=metadata&id=0&period=315d0473-9ff8-4828-83fd-
96fdc36ed618&max-entries=100&marker= 当前的 marker&rgwx-zonegroup=7085627f-27f8-
4779-9552-ebdd13c265e2 HTTP/1.1
 HTTP/1.1 200 OK
Content-Length: 598
{
"marker": "1_1598774754.303770_13.1"
"entries": [
  {
   "timestamp": "2020-08-30 08:05:54.234410256Z"
   "section": "user"
   "data": {
    "status": {
     "status": "write"
...
}

如果从主数据中心拉取 MDlog 请求时有新的 MDlog 返回,发起拉取请求的 RGW 则进入 MDlog 的处理流程,即发送新的获取元数据请求到 Master Zone Group 去拉取新的信息覆盖本地旧的元数据信息。如下为在 Master Zone Group 中创建一个用户后,非 Master Zone Group 向 Master Zone Group 的网关发起的拉取用户信息的请求。

GET /admin/metadata/user/user001?key=user001&rgwx-zonegroup=abc HTTP/1.1
HTTP/1.1 200 OK
Content-Length: 713
{
"data": {
...
  "default_storage_class": ""
  "keys": [
   {
    "access_key": ""
    "secret_key": ""
    "user": "user001"
   }
  ]
...
}

拉取到新的用户信息写入本地集群后,更新 marker 参数,这样在下一个 20s 时带上该 Marker 参数,就会只返回本 Zone 没有的 MDlog,对处理过的 MDlog 就不会返回,从而实现了元数据的增量更新。

RGW 进程只有同时满足如下条件,才会进行 MDlog 的记录。

rgw_zonegroup 为 Master Zone Group。

当前的 Zone Group内的 Zone个数多于 1个或者当前 Realm下的 Zone Group多于 1个。

(3)示例:非主数据中心创建桶

用户信息在 Master Zone Group 中创建后通过 MDlog 的方式同步到其他 Zone Group下所有的 Zone 中,例如非 Master Zone Group 下的某个 RGW 网关接收到创建桶的请求,该 RGW 网关会将请求转发到 Master Zone Group 的网关处理。

void RGWCreateBucket::execute()
{
...
if (!store->svc.zone->is_meta_master()) {
  JSONParser jp;
  op_ret = forward_request_to_master(s NULL store in_data &jp);
...
}

如果主数据中心创建失败(例如主数据中心没有该用户,该用户在非 Master Zone Group 中创建),则创建桶失败。因此所有用户必须在 Master Zone Group 中创建,并通过 MDlog 同步到其他数据中心,用户的修改和删除也必须在 Master Zone Group 中执行。如果 Master Zone Group 成功返回转发创建桶的请求,则继续执行剩余的创建桶流程,将 bucket info 保存到本数据中心的 RADOS。Master Zone Group 接收到该创建桶的请求后,其下的 RGW 也会执行 RGWCreateBucket::execute()。由于它是主数据中心,同时也会记录 MDlog,在元数据同步线程中 MDlog 会克隆到其他 Zone Group,所有的 Zone Group 下都会保存该 bucket info 信息,例如 Master Zone Group 为 beijing1,创建桶的请求发到 Zone Group 为 beijing2 的 RGW 网关,这个请求会被 beijing2 的 RGW网关转发到 beijng1 的 RGW 网关,同时 MDlog 信息会被同步到 beijing2、guangzhou1、hunan1 等所有 Zone Group。在创建好桶之后,如果向这个桶上传数据,则需要将上传数据请求发到 Zone Group 为 beijing2 的 RGW 网关。如果上传请求发到 Zone Group 为guangzhou1 的 RGW 网关,guangzhou1 的 RGW 网关会返回 301 状态码,表明请求所访问的桶不在本数据中心。

对于其他桶的元数据操作,大部分的请求会被转发到 Master Zone Group,例如删除桶、设置桶的静态网站、设置桶的多版本控制、设置桶的桶策略、设置桶的 ACL、设置桶的生命周期规则、设置桶的跨域访问配置等。

2. 数据同步

Ceph 的数据同步是指在多数据中心不同 Zone 之间同步用户上传的文件数据。可以将实体数据的同步分为 3 个部分:记录日志、数据更新通知以及数据更新。下面分别介绍。

(1)记录日志

在对数据进行操作时(比如上传、删除等操作),RGW 会记录一些日志信息,为之后的实体数据同步服务。日志主要分两部分。

◆ bucket index log :在更新 bucket index、设置 olh(object logical head,对象逻辑头)时会记录该日志,包含了对象、操作类型等信息;

data log :记录发生变化的 bucket shard 等信息。

在进行同步时,依据 data log,可以知道哪些 bucket shard 发生了数据的变化。而通过 bucket index log,则可以对对应的对象进行操作。比如,index log 中记录的是 add 操作,就会从 Source Zone 获取具体的对象,如果是 remove 操作,就会把相应的对象删除。

(2)数据更新通知

与元数据同步类似,实体数据的同步同样拥有一个线程周期性地进行数据更新通知。

初始化

实体数据的更新通知由 RGWDataNotifier 线程负责。它的初始化以及启动都是在RGWRados 的初始化函数中。

data_notififier = new RGWDataNotififier(this);
data_notififier->start();

运行

在被启动之后,每隔一段时间(由 rgw_md_notify_interval_msec 配置,默认 200ms)会进行数据更新通知,将记录在 data log 中发生变化的 shard 发送到其他 Zone。其他Zone 在接收到更新通知后,会唤醒相应的数据同步线程。

(3)数据更新

为了与不同的 Zone 进行实体数据的同步,RGW 会启动单独的同步线程。

初始化

数据同步线程的初始化,同样在 RGW 的初始化中,数据同步线程可能会有多个。对于需要进行数据同步的 Zone,都会启动一个线程来专门负责从该 Zone 获取同步数据。

运行

同步线程启动之后,会开始调用 RGWDataSyncProcessorThread 的 process 来对数据进行处理,其主要流程如下。

1)从 RADOS 中读取 data sync status,以及各个 Log shard 的 sync marker。如果是第一次同步,RADOS 中还不存在这些信息,会先对 status 进行初始化。

2)

data sync status 共 有 3 种 状 态, 即 StateInit、StateBuildingFullSyncMaps、StateSync。依据状态的不同,会执行不同的操作。

a)

StateInit :该状态下,会执行一些同步的初始化操作,例如,往 Log Pool 中写入sync_status 对象,从远端获取各个 Log shard 的 sync marker 写入 Log Pool,将 sync_status 设置为 StateBuildingFullSyncMaps 等。

b)

StateBuildingFullSyncMaps :该状态下,会从远端获取所有的 bucket 信息。之后,会以 bucket shard 为单位,将所有需要同步的 bucket shard 写入 OMAP 中,并更新 Log shard 的同步 marker,最后将状态置为 StateSync。

c)

StateSync :该状态即为正常的同步状态,在进行同步时,以 Log shard 为单位,对每一个 Log shard 进行数据同步操作。

3)在对某个 Log shard 进行数据同步时,依据 Log shard 的 sync marker 来判断执行全量还是增量同步。同样,在执行过一次全量同步后,之后执行的就是增量同步了。

4)在每一个 Log shard 中,包含了多个条目,每一个条目是一个 bucket shard 信息。对 Log shard 的同步,实际上就是遍历并同步这些 bucket shard。

5)同步 bucket shard 过程中有不同的状态。依据不同的状态,来依次执行初始化、全量同步以及增量同步。同样,初始化与全量同步只会执行一次,之后便是增量同步。为了同步 bucket shard,RGW 会从对端 Zone 的 RGW 获取该 bucket shard 的 bucket index log,并依据这些 Log,最终决定是从远端获取实体对象,还是从本地删除对象,或者进行其他的操作,此时才会涉及真正的实体数据的操作。

(4)删除日志

如果不删除日志,则随着时间的增加,日志会越来越大。因此,RGW 每隔一段时间都会删除已经同步完成的数据日志。间隔时间由 rgw_sync_log_trim_interval 确定,默认是1200s。在进行日志删除时,需要从各个 Zone 获取数据同步状态信息,并根据这些信息,判断出哪些日志已经被同步完成了,并将其从 RADOS 中删除。

(5)总结

从实体数据同步过程中可以看到涉及多种同步状态的判断。之所以有这么多的状态,是因为 RGW 在进行数据同步时,将其在逻辑上分成了多个层级。我们可以将同步的层级分成如下 4 个层次。

1)Zone 级别

该层级表示了与某个 Zone 的同步状态,表征该层级的同步状态由下面的结构给出。

struct rgw_data_sync_info {
  enum SyncState {
  StateInit = 0 
  StateBuildingFullSyncMaps = 1
  StateSync = 2
  };
  uint16_t state;
  uint32_t num_shards;
  r

2)Log shard 级别

记录数据变化时会将日志分成多个 Log,从而在数据量较大时,获得较好的性能。下面是表示 Log shard 层级的同步状态结构。

struct rgw_data_sync_marker {
enum SyncState {
  FullSync = 0
  IncrementalSync = 1
};
uint16_t state;
string marker;
string next_step_marker;
uint64_t total_entries;
uint64_t pos;
real_time timestamp;
rgw_data_sync_marker() : state(FullSync) total_entries(0) pos(0) {}
}

3)bucket shard 级别

默认情况下,bucket shard 大小为 0。但为了让单个容器可以承载更多的对象,不得不以牺牲 list 对象的性能为代价,增大 bucket shard 的值。目前在线上环境中,该值通常都不配置为 0。因此,我们可以认为,每个 bucket 实际上都存在多个 shard,各自承载着部分对象。而在同步过程中,每一个 bucket shard 都归属于某个 Log shard。对于 log shard 的同步,实际上就是对其下的各个 bucket shard 进行同步。

4)对象级别

在每一个 bucket shard 中都保存了很多对象,同步 bucket shard,就是同步其下面的这些对象。该层级涉及对实体数据的操作,并且也是同步过程中的最底层(不考虑RADOS),没有专门的结构来保存同步信息。


3. 小结

因为 Multisite 是一个 Zone 层面的功能处理机制,所以默认情况下是 Zone 级的数据同步,即配置了 Multisite 之后,整个 Zone 中的数据都会被同步处理。

整个 Zone 层面的数据同步,操作粒度过于粗糙,在很多场景下都是非常不适用的。当前,Ceph RGW 还支持通过 bucket sync enable/disable 来启用 / 禁用存储桶级的数据同步,操作粒度更细,灵活度也更高。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
存储 关系型数据库 MySQL
MySQL——数据库备份上传到阿里云OSS存储
MySQL——数据库备份上传到阿里云OSS存储
165 0
|
2月前
|
分布式计算 DataWorks 调度
oss数据同步maxcompute报错
在使用阿里云DataWorks同步OSS数据至MaxCompute时,遇到“Input is not in the .gz format”的报错。问题源于目标目录中存在一个空文件,导致同步时识别错误。
|
10天前
|
缓存 前端开发 安全
数据同步原理
数据同步原理
41 10
数据同步原理
|
14天前
|
存储 弹性计算 数据管理
阿里云对象存储OSS收费标准,存储、流量和请求等多个计费项
阿里云对象存储OSS提供按量付费与包年包月两种计费方式,涵盖存储、流量、请求等费用。标准存储按量付费0.09元/GB/月,包年包月40GB起售,价格9元/年。公网流量出方向收费,内网及上传免费。具体费用视使用情况而定,详情见官网。
120 0
|
2月前
|
存储 API Swift
Ceph Reef(18.2.X)之Swift操作对象存储网关
这篇文章详细介绍了Ceph Reef(18.2.X)中通过Swift API操作对象存储网关的方法,包括创建用户、子用户、配置环境变量、以及使用swift命令行工具进行存储桶和对象的管理。
35 7
Ceph Reef(18.2.X)之Swift操作对象存储网关
|
2月前
|
存储 对象存储
Ceph Reef(18.2.X)的对象存储网关(rgw)组件搭建
这篇文章是关于Ceph Reef(18.2.X)版本中对象存储系统的配置和使用案例,包括对象存储网关的概述、核心资源介绍、Ceph RGW支持的接口、高可用radosgw的部署、s3cmd工具的使用以及如何通过HTTP方式访问对象存储。
76 3
Ceph Reef(18.2.X)的对象存储网关(rgw)组件搭建
|
2月前
|
存储 监控 数据可视化
SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
【9月更文挑战第2天】SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
150 9
|
2月前
|
对象存储 Python
Ceph Reef(18.2.X)之python操作对象存储网关
这篇文章介绍了如何在Ceph Reef(18.2.X)环境中使用Python操作对象存储网关(rgw),包括环境搭建、账号创建、使用s3cmd工具以及编写和测试Python代码。
49 3
|
3月前
|
存储 关系型数据库 MySQL
【TiDB原理与实战详解】5、BR 物理备份恢复与Binlog 数据同步~学不会? 不存在的!
BR(Backup & Restore)是 TiDB 分布式备份恢复的命令行工具,适用于大数据量场景,支持常规备份恢复及大规模数据迁移。BR 通过向各 TiKV 节点下发命令执行备份或恢复操作,生成 SST 文件存储数据信息与 `backupmeta` 文件存储元信息。推荐部署配置包括在 PD 节点部署 BR 工具,使用万兆网卡等。本文介绍 BR 的工作原理、部署配置、使用限制及多种备份恢复方式,如全量备份、单库/单表备份、过滤备份及增量备份等。
|
3月前
|
存储 JavaScript 前端开发
Vue中实现图片上传,上传后的图片回显,存储图片到服务器 【使用对象存储OSS】
这篇文章介绍了在Vue中实现图片上传到阿里云OSS对象存储服务的完整流程,包括服务端签名直传的前提知识、后端设置、前端组件封装以及图片上传和回显的效果展示。

热门文章

最新文章