唯一ID:雪花算法介绍与 Go 语言实现

介绍

snowflake 雪花算法可以在不依赖数据库的情况下,生成全局唯一的ID。雪花算法生成的ID是一个64位的整数,它由以下4部分组成:

  1. 时间戳:占用41位,精确到毫秒级,用于记录时间戳,差值形式可以使用69年。
  2. 数据中心ID:占5位,可以部署32个数据中心。
  3. 机器ID:占5位,每个数据中心可以有32台机器。
  4. 序列号:占用12位,每个节点每毫秒最多可以生成4096个ID。

组成 [1][41][5][5][12] ,其中第一位是符号位默认值为0。

工作原理:

  1. 使用配置文件或环境变量确保不同数据中心和机器节点拥有唯一ID。
  2. 设置时钟回拨处理策略,使用NTP服务同步时钟。
  3. 当一个节点在同一毫秒内请求多个ID时,会通过增加序列号的方式来保证ID的唯一性。

下面将使用 GO 语言简单实现雪花算法。

实现

纪元

因为雪花算法中时间戳是根据当前时间戳与纪元时间戳做差得出的,所以我们得先设定一个纪元时间戳。

Go 语言中 UnixMill 可以将当前时间转化为精确到毫秒的时间戳,所以我们打算使用 UnixMill 将当前时间转换为时间戳作为纪元时间戳。

package mainimport ("fmt""time"
)func main () {// 获取当前时间now := time.Now()// 获取时间戳timestamp := now.UnixMilli()fmt.Println(timestamp)// 人类可读形式humanReadable := now.Format("2006-01-02 15:04:05")fmt.Println(humanReadable)
}

最大值

为了方便接口设计,我们去掉了数据中心,只剩下时间戳、机器ID和序列号。为了方便边界判断,我们需要设定常量记录它们的最大值。为了方便拼接将时间戳、机器ID和序列号拼接成最终结果,我们还需要记录它们的偏移量,具体实现如下:

const (epoch             int64 = 1719562568879 // 设置起始时间戳,例如2021-01-01 00:00:00 UTCtimeBitLength     uint8 = 41            // 时间戳占用的位数workerIDBitLength uint8 = 5             // 工作机器ID占用的位数sequenceBitLength uint8 = 12            // 序列号占用的位数maxWorkerID     int64 = -1 ^ (-1 << workerIDBitLength) // 工作机器ID的最大值maxSequence     int64 = -1 ^ (-1 << sequenceBitLength) // 序列号的最大值timeShift       uint8 = workerIDBitLength + sequenceBitLengthworkerIDShift   uint8 = sequenceBitLengthtwepoch         int64 = epoch
)

Snowflake 结构体

snowflake 结构体包括一把互斥锁,以及组成唯一ID的三部分,具体实现如下:

type Snowflake struct {mu        sync.Mutextimestamp int64workerID  int64sequence  int64
}

初始化结构体

同一台机应该使用唯一的 Snowflake 对象,初始化时赋予其合法且唯一的 workerID。

func NewSnowflake(workerID int64) (*Snowflake, error) {if workerID < 0 || workerID > maxWorkerID {return nil, errors.New("worker ID out of range")}return &Snowflake{timestamp: 0,workerID:  workerID,sequence:  0,}, nil
}

生成ID

  1. 在同一台机器上为避免生成重复的ID,我们应该在生成ID之前,先获取互斥锁。
  2. 拿到锁之后,利用当前时间戳与纪元时间戳做差得到 timestamp 的值。
  3. 比较当前timestamp 与结构体中的 timestamp。
    • 如果当前值更小,说明发生了时钟回拨,抛出异常拒绝生成ID。
    • 如果 timestamp 值相等,那么说明是同一毫秒内生成不同序列号
      • 如果可用序列号没有用完则递增生成序列号
      • 如果序列号用完,循环回0,则等待下一毫秒的到来。
    • 如果 timestamp 值不同,那么说明时新值,将序列号置零。
  4. 组合时间戳、机器ID和序列号得到唯一ID。
func (s *Snowflake) Generate() (int64, error) {s.mu.Lock()defer s.mu.Unlock()now := time.Now().UnixMilli() - twepochif now < s.timestamp {return 0, errors.New("clock is moving backwards")}if now == s.timestamp {s.sequence = (s.sequence + 1) & maxSequenceif s.sequence == 0 {for now <= s.timestamp {now = time.Now().UnixMilli() - twepoch}}} else {s.sequence = 0}s.timestamp = nowid := ((now << timeShift) | (s.workerID << workerIDShift) | (s.sequence))return id, nil
}

使用

上面内容完成后,只要先创建 Snowflake 对象,然后再调用 Generate 函数便可以生成唯一ID。

func main() {sf, _ := NewSnowflake(1) // Assuming workerID 1 is validfor i := 0; i < 1000; i++ {id, err := sf.Generate()fmt.Println(id)}
}

特点

1.高性能:ID生成过程完全在内存中完成,高效且延迟低。
2.高可用:ID的生成在本地完成,不会因为单点故障而影响其他节点ID的生成。
3.无中心化:不依赖于外部系统,如数据库,避免复杂的依赖和潜在的性能瓶颈。
4.可排序:由于ID的前部是基于时间的,所以生成的ID自然是按时间顺序增加的。

注意事项

使用时应注意统一所有节点时钟,并且设计好时钟回拨时的处理方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/38709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库设计规范详解

一、为什么需要数据库设计 1、我们在设计数据表的时候&#xff0c;要考虑很多问题。比如: (1) 用户都需要什么数据?需要在数据表中保存哪些数据? (2) 如何保证数据表中数据的 正确性&#xff0c;当插入、删除、更新的时候该进行怎样的 约束检査 ?. (3) 如何降低数据表的 数据…

每天一个数据分析题(三百八十五)- 回归模型

在回归模型中&#xff0c;下列哪一项在权衡欠拟合&#xff08;under-fitting&#xff09;和过拟合&#xff08;over-fitting&#xff09;中影响最大&#xff1f; A. 多项式阶数 B. 更新回归参数w时&#xff0c;使用的是协方差矩阵求逆还是梯度下降 C. 使用常数项 D. 以上都…

python导入未找到tensorrt,No module named ‘tensorrt‘

(2024.7.1) 这个错误可能比较少见&#xff0c;是因为本人先装了tensorrt 10.1&#xff08;能够正常运行&#xff09;&#xff0c;后面又装了nvidia-tensorrt 7&#xff0c;后面不想用7了就把7卸了用回10&#xff0c;结果即使同一版本的tensorrt和nvidia-tensorrt都装了&#x…

毫米波雷达深度学习技术-2.1~2.2深度度量学习和成对方法

2 深度度量学习 有几种雷达应用程序旨在对一组预定义的类别进行分类&#xff0c;例如不同的人类活动或手势。然而&#xff0c;在实际环境中&#xff0c;存在的类不仅仅是预定义的类&#xff0c;这就把问题变成了一个开放集的分类任务。开放集分类意味着网络应该能够检测输入是否…

[AIGC] StarRocks 快速了解

星石数据库&#xff08;StarRocks&#xff09;是一种高性能、分布式的列式存储数据库系统&#xff0c;旨在为大规模数据分析提供快速和可靠的解决方案。它由StarRocks团队于2015年开始开发&#xff0c;最初是由中国电子科技集团公司&#xff08;CETC&#xff09;内部项目&#…

Chapter 8 Feedback

Chapter 8 Feedback 这一章我们介绍feedback 反馈运放的原理. 负反馈是模拟电路强有力的工具. 8.1 General Considerations 反馈系统如下图所示 Aolamp open-loop gain即开环增益. Aolxo/xi β \beta β 是 feedback factor, 注意方向. β x f x o \beta\frac{x_{f}}{x_{o…

Python内置函数enumerate 将可迭代对象组合成索引序列列举出数据和数据下表

enumerate 是一个内置的 Python 函数&#xff0c;用于将一个可迭代对象&#xff08;如列表、元组、字符串等&#xff09;组合为一个索引序列&#xff0c;同时列出数据和数据下标。 参数说明&#xff1a; enumerate(iterable, start0) 接受两个参数&#xff1a; iterable&…

从零开始:Java开发者的设计模式指南

从零开始&#xff1a;Java开发者的设计模式指南 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Java开发中的设计模式&#xff0c;这是每位J…

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化)

一、课程介绍&#xff0c;基础—环境安装、判断、循环语句等&#xff08;爬虫及数据可视化&#xff09; 1. 课程介绍1.1 相关内容1.2 学习目标1.3 学习内容安排 2. python2.1 环境配置2.2 标识符和关键字2.3 运算符2.4 判断语句2.5 循环语句 1. 课程介绍 1.1 相关内容 10天的…

【pytorch11】高阶操作

高阶操作 WhereGather where 三个参数&#xff0c;第一个是condition&#xff0c;第二个参数是源头A&#xff0c;第三个参数是源头B&#xff0c;也就是说有两项数据A和B&#xff0c;C有可能来自于A也有可能来自于B&#xff0c;如果全部来自于A的话直接赋值给A&#xff0c;如果…

算法金 | Transformer,一个神奇的算法模型!!

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 在现代自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;Transformer 模型的出现带来了革命性的变…

推送本地代码库到gitee

方式一&#xff1a; 1、在gitee创建代码库 2、下拉到本地 git clone https:xxxx 3、将要上传的代码复制进去 4、git add . 5、git commit -m 6、git push -u origin master 成功 方式二&#xff1a; 1、在gitee创建代码库 2、将要上传的代码库执行 git init 3、gi…

无线物联网练习题

文章目录 选择填空简答大题 选择 不属于物联网感知技术的是(A) A:ZigBee B:红外传感器 C:FRID D:传感器 ZigBee是一种无线通信技术&#xff0c;虽然它常用于物联网中作为设备之间的通信手段&#xff0c;但它本身并不是一种感知技术 关于物联网于与互联网的区别的描述&#xff…

【机器学习】基于Transformer的迁移学习:理论与实践

引言 在机器学习领域&#xff0c;迁移学习已成为提升模型训练效率和性能的重要策略&#xff0c;特别是在标注数据稀缺的场景下。Transformer模型自2017年由Google提出以来&#xff0c;在自然语言处理&#xff08;NLP&#xff09;领域取得了突破性进展&#xff0c;并逐渐扩展到…

map和set的底层实现

前言 map和set的底层都是由红黑树构成&#xff0c;但是map是kv模型&#xff0c;set是k模型。如何用一颗子树来同时封装map和set&#xff0c;还有怎么实现map/set的迭代器是这节重点 map和set的模板参数 struct MapKeyOfT{const K& operator()(const pair<K, V>&am…

XF 533-2012 挡烟垂壁

挡烟垂壁是指用不燃材料制成&#xff0c;垂直安装在建筑顶棚、横梁或吊顶下&#xff0c;能在火灾时形成一定的蓄烟空间的挡烟分隔设施。 XF 533-2012 挡烟垂壁测试项目 测试要求 测试标准 外观 XF 533 材料 XF 533 尺寸与极限偏差 XF 533 漏烟量 XF 533 耐高温性能 …

Zuul介绍

Zuul 是 Netflix 开源的一个云平台网络层代理&#xff0c;它主要用于路由、负载均衡、中间件通信和动态路由。Zuul 本质上是一个基于 JVM 的网关&#xff0c;它提供了以下功能&#xff1a; 1.路由&#xff1a;Zuul 允许客户端和服务器之间的所有入站和出站请求通过一个中心化的…

gbase8s数据库中根据系统表查看锁的现状和锁资源的监控(包括了两个onstat -g的关键命令和锁的查看演示)

1. 锁资源信息的查找和监控 1.1. 系统表中关于锁的信息 1.1.1. 当前正在占用锁资源和等待锁资源信息的系统表syslocks和测试 > select * from sysmaster:syslocks; dbsname test --数据库名称 tabname test --锁发生的表名称 rowidlk 6918 --发生锁的行号 keynum …

小红书怎么保存无水印图?

使用小红书APP长按保存的图片代有水印&#xff0c;很多人想知道保存小红书无水印图片的方法。本文教你如何保存到无水印的小红书图片&#xff0c;但是请注意不要侵犯作者图片的版权。 小红书怎么保存无水印图&#xff1f; 1、手机上打开小红书APP&#xff1b; 2、打开后&#…

昇思25天学习打卡营第13天|BERT

一、简介&#xff1a; BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c;它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自…