`

【分布式ID】【Snowflake变种】用 ZooKeeper 维护 Worker ID

    博客分类:
  • Java
阅读更多

Twitter 推出的 Snowflake 是一个非常实用的分布式ID生成方案。它的默认设置中,各部分信息所占比特位比较有代表性,通常无需二次定制。但是对于 datacenter id 和 worker id 的维护需要各项目自行设计方案。
 

通常,datacenter id 是固定的,一旦为各数据中心分配好ID,几乎不会变更。但各数据中心内部的 worker id 可能会因ID生成服务实例的动态创建销毁,而需要有一套动态的协调机制,以防同一数据中心内多个实例共用同一个 worker id。
 

本例就是利用 ZooKeeper 来协调分配 worker id。
源码:snowflake-worker-id-with-zk
 

关键类:IdGenCoordinator

此类用于协调分配 worker id。
 

基本原理

基本原理是 以创建 ZooKeeper 节点的方式来表示哪些 worker id 已被占用。
节点树结构示例:


 

  • /example/id-gen/worker-ids 的子节点表示当前已被占用的 worker id。
    其中各节点内容就是使用该 worker id 的id生成器实例的ip地址。
  • /example/id-gen/gens 的子节点表示当前活跃的id生成生成器实例。
    其中各节点内容就是相应生成器实例所使用的 worker id。

 

初始化步骤

  • 1. 创建必要的 ZooKeeper 父节点。
    “/example/id-gen/worker-ids” 和 “/example/id-gen/gens” 是必要的父节点。注意,需要处理 NodeExistsException,因为各 id 生成器实例启动时都会执行该操作。
  • 2. 注册 ZooKeeper 连接状态变更事件处理器。
    防止多个 id 生成器服务实例使用同一个 worker id。
  • 3. 获取 worker id 并启动 id生成器服务
(查看源码 init() 方法)

 

ZooKeeper 连接状态处理

  • 当生成器与 ZooKeeper 断开连接时,需停止服务,以防多个生成器实例使用同一个 worker id;
  • 当生成器与 ZooKeeper 重新连接时,需重新获取 worker id,因为原 worker id 可能已被其它实例占用。
(查看源码 registerConnStateListener() 方法)

 

获取 worker id 的关键逻辑

  • 1. 尝试获取对应的 ZK 节点内容。
    如 “/example/id-gen/gens/10.1.100.101”。
    若成功获取,说明该服务实例已注册,节点内容就是已分配给它的 worker id;否则进行下一步:注册。
  • 2. 从最小 worker id 开始,至最大 worker id,尝试创建相应的 ZK 节点。
    若创建成功,则表示成功获得相应的 worker id。否则认定为失败。

需要创建两个节点,且必须在同一个ZooKeeper事务中完成。如,在一个事务中创建:
/example/id-gen/worker-ids/0 (节点内容为 10.1.100.101)
/example/id-gen/gens/10.1.100.101 (节点内容为 0)

(查看源码 getWorkerId() 方法)

 

  • 大小: 42.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics