欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-30 10:49:30
...

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 已被占用。
节点树结构示例:

【分布式ID】【Snowflake变种】用 ZooKeeper 维护 Worker ID
            
    
    博客分类: Java  
 

  • /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() 方法)

 

  • 【分布式ID】【Snowflake变种】用 ZooKeeper 维护 Worker ID
            
    
    博客分类: Java  
  • 大小: 42.3 KB