当前位置: 首页 > news >正文

如何实现一个64 bit ID Unique Generator

如何实现一个64 bit ID Unique Generator

Requirements

  • 要求ID唯一但非自增长
  • 高性能,节点/实例可以扩展 (Scability)
  • 节点/实例重启后可以接着分配ID (Durability)

Scability 的考虑

要求可以多实例扩展,那就需要每个实例需要有唯一的Identity来参与生成 ID 的分段。

如果这个实例是无状态实例,那么这个实例被scale in 之后,该 identity 分段的ID 也不能就此废弃,等新的实例被scale out 出来后,需要重复利用这个分段的ID.

为什么不能使用有状态的实例, 使用实例自身状态的identity 来做分段呢? 例如 POD-0, POD-1 之类的就用 0,1 之类的来标识分段。 因为这样的话,假如 0 标识的这个分段用完了,那 POD-0 就不能再 分配ID 了。
而如果无状态的POD, 而 Identity 是从其他地方获取的,和自身无关,那么这个identity 用完了,可以申请获取新的identity,然后又可以重新分配新的段的ID 了。

这里可以使用zookeeper 来分配 instance 的 identity.

Durability

当实例或者说pod 重启之后,client 重新申请ID 时,可以被分配到没有被使用的ID 或者是接着之前用的ID 段的新ID.

那就需要将这部分的已经分配了哪些 ID 的 信息/状态 保持到数据库中,以实现持久化。

实现

ID 的结构如下,其中每个worker 可用的位数是 40 bit, 如果按照1000 tps 来算,每个实例可以使用 34 年。计算公式如下 (2^40 -1 )/1000/31536000 = 34 years.

+--------+-----------+----------------+----------------------------------------+
| 63     | 62 - 56   | 55 - 40        | 39 - 0                                 |
+--------+-----------+----------------+----------------------------------------+
| sign   |  zone id  |   worker id    |               sequence                 |
| 1 bit  |  7 bits   |    16 bits     |               40 bits                  |
+--------+-----------+----------------+----------------------------------------+sign:最高位(第63位),表示符号位(一般为0表示正数)。zone id:接下来的7位(62到56),代表逻辑区域或机房。worker id:16位(55到40),代表节点/实例/POD的 ID。sequence:剩下的40位(39到0),表示这个段内可用的 ID。

这个ID Generator 的实现可以是一个lib,也可以是一个service.

以lib 的实现方式为例子, 需要提供一个接口来分配ID.


public long next();

lib 也需要连接 zookeeper 去获取worker ID, 去 数据库 存放 当前这个worker ID 最大已经分配到那个ID 了。
还需要一些配置来定义是属于那个business 的, 以便在 zookeeper 创建对于的 属于这个 business 的 worker 节点。 例如 /idg/business-1/worker-- 这种znode.

而 parent znode /idg/business-1 是持久化的,而子节点 worker-N 这种节点就是 临时节点。 在parent 节点上的value 上持久化worker ID 和 instance/POD 的mapping关系。 例如

{"workerId2Node":{"2":"/idg/business-1/_w_-144807203059138568-0000000002","3":"/idg/business-1/_w_-144807203059138569-0000000003","0":"/idg/business-1/_w_-144807472447553536-0000000004","1":"/idg/business-1/_w_-144807472447553537-0000000005"}}

这样当POD 连接到zk 的时候,就可以通过子节点的名字就可以知道自己有没有已经分配到 worker ID 了,如果没有就新创建一个。 如果有,则可以通过读取worker-N 的这种临时节点的内容去获取worker ID.

另外一个问题是,假如一个pod 断开很久,临时节点已经消失了,那重新连接上ZK,那么之前旧的worker id mapping信息依然存在于parent 节点,但是其实际对应的临时节点已经消失了。 这个时候就可以重新读取parent 节点下所有的子节点list,然后比较parent节点的value来去掉value 中已经不存在的mapping信息对,并且排序查看那个worker ID对应的mapping 信息被去掉了,那就重新使用这个已经不存在mapping信息的 worker ID 来关联本session. 这样就可以达到复用 worker ID 的目标了。

另外一个就是lib 可以在申请ID 时,可以一段一段地申请。 例如一次申请1000 个ID 来允许 next() 接口使用。
next() 接口使用的ID 已经不够 500 了,就触发异步线程获取另外 1000 个ID 来备用。

http://www.lqws.cn/news/446923.html

相关文章:

  • Laravel框架的发展前景与Composer的核心作用-优雅草卓伊凡
  • 大数据复习HDFS
  • 苍穹外卖-2025 完成基础配置环节(详细图解)
  • 端口安全配置示例
  • golang excel导出时需要显示刷新
  • go客户端ssh交换机
  • Mysql5.7 自动备份恢复示例
  • 渗透实战:绕过沙箱机制的反射型XSS
  • ROS学习之动作通信
  • 苍穹外卖--WebSocket、来单提醒、客户催单
  • 图像特征检测算法ORB
  • ros中相机话题在web页面上的显示,尝试js解析sensor_msgs/Image数据
  • 动态规划:01 背包(闫氏DP分析法)
  • Linux系统远程操作和程序编译
  • JS红宝书笔记 - 8.1 理解对象
  • 零基础指南:利用Cpolar内网穿透实现Synology Drive多端笔记同步
  • PHP 生成当月日期
  • 解决 Docker 里 DrissionPage 无法连接浏览器的问题,内含直接可用的Docker镜像(DrissionPage 浏览器链接失败 怎么办?)
  • 23种设计模式--简单工厂模式理解版
  • 日本生活:日语语言学校-日语作文-沟通无国界(3)-题目:わたしの友達
  • 基于 Web 的 3D 设计工具Spline介绍
  • 理解服务注册与发现
  • DeserializationViewer使用说明
  • java IO流
  • Git vs Perforce P4:版本控制系统选型指南(附适用场景、团队类型)
  • 【嵌入式】鲁班猫玩法大全
  • LVDS接口
  • 华为网路设备学习-25(路由器OSPF - 特性专题 二)
  • vscode设置代码字体
  • repo 工具