searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一种Zookeeper数据同步方案

2023-08-02 00:29:25
18
0

数据机制

Zookeeper提供的命名空间非常像一个标准的文件系统,节点名称由斜杠(/)分隔的路径元素构成,在Zookeeper命名空间中的节点通过路径进行标识。

[Zookeeper的层级命名空间]

与标准的文件系统不同,Zookeeper命名空间中的每个节点都可以关联数据和子节点,这就好像拥有一个支持既是文件也是目录的文件系统。(Zookeeper设计上是用于存储协调数据的:状态信息、配置、地址信息等,所以每个节点上保存的数据通常比较小,一般是KB级别。)

我们使用术语znode表示Zookeeper的数据节点,除数据外,znode包含以下统计属性:

节点属性

说明

cZxid

触发znode创建的事务ID

ctime

znode创建毫秒时间戳

mZxid

触发znode最近修改的事务ID

mtime

znode最近修改毫秒时间戳

pZxid

触发znode最近子节点变更(仅列表)的事务ID

cversion

znode子节点变更版本号

dataVersion

znode数据变更版本号

aclVersion

znode访问控制列表(ACL)变更版本号

ephemeralOwner

临时节点所属的sessionID,如果非临时节点,则为0

dataLength

znode数据长度

numChildren

znode子节点数据

znode包含多种类型,按持久化、顺序和失效机制,可分为以下几类:

节点类型

说明

持久节点(persistence znode)

不管客户端是否连接,该节点都存在有效,默认情况下所有节点都是持久的

临时节点(ephemeral znode)

临时节点的生命周期和客户端会话绑定在一起,客户端会话失效,则这个节点就会被自动清除

顺序节点(sequential znode)

表示节点顺序关系,创建时在路径后附加递增序号,序号在父节点下唯一,它也分为持久的和临时的

容器节点(container znode)

当容器节点的子节点数量为0时,会自动删除该节点,除此之外和持久节点没有区别

TTL节点(ttl znode)

针对持久或持久顺序节点,可以设置生存时间(Time To Live),当节点在TTL时间内未修改且没有子节点,将自动被择机删除

Zookeeper提供一套watch机制监听znode变更, 在3.6.0(不含)之前watch事件的触发是一次性的,即当设置的watch关注的数据更新时,会发送相应的watch事件给客户端,但后续znode再次更新时,就不会再发送watch事件了,除非客户端再次设置新的watch进行监听。一次性的触发机制存在获取当次watch事件和发起下次watch监听的延迟,如果znode变更频繁,将无法感知此期间的变更,使用时需了解这种情况并做对应处理。

在3.6.0(含)之后,Zookeeper支持设置持久化(触发后不移除)递归(在子节点上递归注册)的watch监听,可以避免上面监听空窗期事件丢失问题,主要支持下列事件:

  • NodeCreated
  • NodeDeleted
  • NodeDataChanged

同步设计

依赖watch机制实现znode数据逻辑同步结构如图:

  • FullExtracter:全量数据抽取,通过遍历节点和数据实现
  • IncrementExtracter:增量数据抽取,通过监听节点事件实现
  • DataTransformer:数据转换,将全量抽取和增量抽取的数据转换为待装载数据
  • FullQueue:全量数据队列,全量数据抽取的待装载数据
  • IncrementQueue:增量数据队列,增量数据抽取的待装载数据
  • DataLoader:数据装载,从数据队列中读取数据并写到目标实例

数据同步分为全量同步和增量实时同步两个过程,但这两个过程不是串行的,而是交错运行,关注几点:

  1. 增量过程的事件监听需早于全量过程,避免监听空窗期数据变更丢失,如:

  1. 全量过程的数据装载需判断数据版本,避免覆盖增量过程的较新数据,如:

  1. 增量过程的节点更新事件可能早于全量过程的创建行为,需要转换操作,如:

  1. 两次同步间隔的数据依赖全量补齐,需要位点减少重复,如:

综上同步流程如图:

特别地,这里采用逻辑同步Zookeeper数据的方式不考虑ACL数据同步,本方案是模拟Zookeeper客户端读取和监听节点数据,ACL有特殊限制已不满足。如果确有需求,可在znode变更时,增加getACL和setACL操作代替。

另外再讨论不同节点类型对同步流程的影响,原则上同步过程只在目标集群创建持久节点,节点路径和生命周期通过监听源集群的事件来变更:

节点类型

说明

持久节点(persistence znode)

正常同步

临时节点(ephemeral znode)

可以不同步

顺序节点(sequential znode)

根据持久和临时区分

容器节点(container znode)

正常同步

TTL节点(ttl znode)

正常同步

实现方式

Apache Curator是一个比较完善的Zookeeper客户端框架,通过封装的一套高级API,简化了Zookeeper的操作,因此在实际应用中被广泛使用。

Curator的使用比较简单,针对Zookeeper 3.6.0(含)以上版本需要配合5.0.0以上版本使用,重点关注CuratorCache在znode事件监听中的使用,它有几个特点:

  1. 支持节点或子树的本地缓存
  2. 支持响应create/update/delete事件
  3. 支持响应事件时数据前后对比

示例代码:

String connectString = "";
int sessionTimeoutMs = 1000;
int connectionTimeoutMs = 1000;
RetryPolicy retryPolicy = new RetryOneTime(1);
try (CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy)) {
    client.start();
    try (CuratorCache cache = CuratorCache.build(client, "/test")) {
        cache.listenable().addListener((type, oldNode, node) -> {
            switch (type) {
                case NODE_CREATED:
                case NODE_CHANGED:
                case NODE_DELETED:
            }
        });
    }
}
0条评论
0 / 1000
陈一之
21文章数
2粉丝数
陈一之
21 文章 | 2 粉丝
原创

一种Zookeeper数据同步方案

2023-08-02 00:29:25
18
0

数据机制

Zookeeper提供的命名空间非常像一个标准的文件系统,节点名称由斜杠(/)分隔的路径元素构成,在Zookeeper命名空间中的节点通过路径进行标识。

[Zookeeper的层级命名空间]

与标准的文件系统不同,Zookeeper命名空间中的每个节点都可以关联数据和子节点,这就好像拥有一个支持既是文件也是目录的文件系统。(Zookeeper设计上是用于存储协调数据的:状态信息、配置、地址信息等,所以每个节点上保存的数据通常比较小,一般是KB级别。)

我们使用术语znode表示Zookeeper的数据节点,除数据外,znode包含以下统计属性:

节点属性

说明

cZxid

触发znode创建的事务ID

ctime

znode创建毫秒时间戳

mZxid

触发znode最近修改的事务ID

mtime

znode最近修改毫秒时间戳

pZxid

触发znode最近子节点变更(仅列表)的事务ID

cversion

znode子节点变更版本号

dataVersion

znode数据变更版本号

aclVersion

znode访问控制列表(ACL)变更版本号

ephemeralOwner

临时节点所属的sessionID,如果非临时节点,则为0

dataLength

znode数据长度

numChildren

znode子节点数据

znode包含多种类型,按持久化、顺序和失效机制,可分为以下几类:

节点类型

说明

持久节点(persistence znode)

不管客户端是否连接,该节点都存在有效,默认情况下所有节点都是持久的

临时节点(ephemeral znode)

临时节点的生命周期和客户端会话绑定在一起,客户端会话失效,则这个节点就会被自动清除

顺序节点(sequential znode)

表示节点顺序关系,创建时在路径后附加递增序号,序号在父节点下唯一,它也分为持久的和临时的

容器节点(container znode)

当容器节点的子节点数量为0时,会自动删除该节点,除此之外和持久节点没有区别

TTL节点(ttl znode)

针对持久或持久顺序节点,可以设置生存时间(Time To Live),当节点在TTL时间内未修改且没有子节点,将自动被择机删除

Zookeeper提供一套watch机制监听znode变更, 在3.6.0(不含)之前watch事件的触发是一次性的,即当设置的watch关注的数据更新时,会发送相应的watch事件给客户端,但后续znode再次更新时,就不会再发送watch事件了,除非客户端再次设置新的watch进行监听。一次性的触发机制存在获取当次watch事件和发起下次watch监听的延迟,如果znode变更频繁,将无法感知此期间的变更,使用时需了解这种情况并做对应处理。

在3.6.0(含)之后,Zookeeper支持设置持久化(触发后不移除)递归(在子节点上递归注册)的watch监听,可以避免上面监听空窗期事件丢失问题,主要支持下列事件:

  • NodeCreated
  • NodeDeleted
  • NodeDataChanged

同步设计

依赖watch机制实现znode数据逻辑同步结构如图:

  • FullExtracter:全量数据抽取,通过遍历节点和数据实现
  • IncrementExtracter:增量数据抽取,通过监听节点事件实现
  • DataTransformer:数据转换,将全量抽取和增量抽取的数据转换为待装载数据
  • FullQueue:全量数据队列,全量数据抽取的待装载数据
  • IncrementQueue:增量数据队列,增量数据抽取的待装载数据
  • DataLoader:数据装载,从数据队列中读取数据并写到目标实例

数据同步分为全量同步和增量实时同步两个过程,但这两个过程不是串行的,而是交错运行,关注几点:

  1. 增量过程的事件监听需早于全量过程,避免监听空窗期数据变更丢失,如:

  1. 全量过程的数据装载需判断数据版本,避免覆盖增量过程的较新数据,如:

  1. 增量过程的节点更新事件可能早于全量过程的创建行为,需要转换操作,如:

  1. 两次同步间隔的数据依赖全量补齐,需要位点减少重复,如:

综上同步流程如图:

特别地,这里采用逻辑同步Zookeeper数据的方式不考虑ACL数据同步,本方案是模拟Zookeeper客户端读取和监听节点数据,ACL有特殊限制已不满足。如果确有需求,可在znode变更时,增加getACL和setACL操作代替。

另外再讨论不同节点类型对同步流程的影响,原则上同步过程只在目标集群创建持久节点,节点路径和生命周期通过监听源集群的事件来变更:

节点类型

说明

持久节点(persistence znode)

正常同步

临时节点(ephemeral znode)

可以不同步

顺序节点(sequential znode)

根据持久和临时区分

容器节点(container znode)

正常同步

TTL节点(ttl znode)

正常同步

实现方式

Apache Curator是一个比较完善的Zookeeper客户端框架,通过封装的一套高级API,简化了Zookeeper的操作,因此在实际应用中被广泛使用。

Curator的使用比较简单,针对Zookeeper 3.6.0(含)以上版本需要配合5.0.0以上版本使用,重点关注CuratorCache在znode事件监听中的使用,它有几个特点:

  1. 支持节点或子树的本地缓存
  2. 支持响应create/update/delete事件
  3. 支持响应事件时数据前后对比

示例代码:

String connectString = "";
int sessionTimeoutMs = 1000;
int connectionTimeoutMs = 1000;
RetryPolicy retryPolicy = new RetryOneTime(1);
try (CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy)) {
    client.start();
    try (CuratorCache cache = CuratorCache.build(client, "/test")) {
        cache.listenable().addListener((type, oldNode, node) -> {
            switch (type) {
                case NODE_CREATED:
                case NODE_CHANGED:
                case NODE_DELETED:
            }
        });
    }
}
文章来自个人专栏
学而时习
21 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0