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

每日一Go-55、分布式 ID 生成(雪花算法 / Segment / Redis / DB)

一、为什么分布式系统一定要“自己造ID”?

单机时代,利用数据库的自增`ID`AUTO_INCREMENT

但是在微服务/多实例/分库分表的情况下,会出现:

  • ID冲突

  • 数据迁移困难

  • 顺序失控

  • 跨库无法唯一定位

二、分布式ID的核心指标

一个靠谱的ID方案,至少要满足:

指标
说明
全局唯一
不能重复
高性能
AQS≥10w
有序性
越新越大
高可用
不能成为单点
易扩展
节点随时加

三、主流4种方案总览

方案
性能
有序
依赖
复杂度
典型
雪花算法
5星
4星
本地
两星
Twitter
Segment号段
4星
5星
DB
3星
美团/京东
Redis INCR
3星
5星
Redis
1星
小系统
DB自增
1星
5星
DB
1星
单体

四、方案1:DB自增

INSERT INTOtVALUES();SELECTLAST_INSERT_ID();

这是所有分布式系统大忌,不推荐。

五、方案2:Redis INCR

// Redis 命令 INCRorder:id // Go调用 id,_:=rdb.Incr(ctx,"order:id").Result()

优点:实现简单;严格递增。

缺点:Redis单点;网络开销;QPS上限。

适合低并发系统/管理后台

六、方案3:Segment号段(美团/京东订单号)

思路:

DB中维护一个号段

一次取一段(例如:1000个)

本地内存自增

表结构:

CREATETABLEid_segment(biz_tagVARCHAR(64)PRIMARYKEY,max_idBIGINT,stepINT);
typeSegmentstruct{curint64maxint64}func(s*Segment)Next()int64{ifs.cur>=s.max{s.reload()}s.cur++returns.cur}

优点:严格递增;ID短

缺点:依赖DB;实现复杂;冷启动慢。

适合订单号、流水号

七、方案4:雪花算法(Snowflake)

1. ID结构

0 | 41bit 时间戳 | 10bit 机器ID | 12bit 序列号

时间戳:毫秒

机器ID:数据中心+worker

序列号:同毫秒并发

趋势递增、完全本地生成、无依赖

2. go 代码实现

packagesnowflakeimport("errors""strconv""sync""time")// 常量定义const(workerBits=10// 工作节点位数seqBits=12// 序列号位数workerMax=-1^(-1<<workerBits)// 工作节点最大IDseqMask=-1^(-1<<seqBits)// 序列号掩码timeShift=workerBits+seqBits// 时间戳左移位数workerShift=seqBits// 工作节点左移位数defaultEpoch=int64(1672531200000)// 默认起始时间戳 (2023-01-01))// ID 自定义类型,用于区分雪花ID和普通int64typeIDint64// Snowflake 雪花算法生成器typeSnowflakestruct{mu sync.Mutex lastTimeint64workerIDint64sequenceint64epochint64}// New 创建雪花算法生成器// workerID: 工作节点ID,范围 0~1023// 返回错误如果workerID超出范围funcNew(workerIDint64)(*Snowflake,error){returnNewWithEpoch(workerID,defaultEpoch)}// NewWithEpoch 创建带自定义起始时间的雪花算法生成器// workerID: 工作节点ID,范围 0~1023// epoch: 自定义起始时间戳(毫秒)// 返回错误如果workerID超出范围funcNewWithEpoch(workerIDint64,epochint64)(*Snowflake,error){ifworkerID<0||workerID>workerMax{returnnil,errors.New("worker ID out of range [0, 1023]")}return&Snowflake{workerID:workerID,epoch:epoch,},nil}// NextID 生成下一个雪花ID// 返回ID类型的雪花ID和可能的错误func(s*Snowflake)NextID()(ID,error){s.mu.Lock()defers.mu.Unlock()now:=time.Now().UnixMilli()// 处理时间回拨ifnow<s.lastTime{return0,errors.New("time is back, ID generation failed")}ifnow==s.lastTime{// 同一毫秒内,递增序列号s.sequence=(s.sequence+1)&seqMask// 序列号耗尽,等待下一个毫秒ifs.sequence==0{// 使用短暂休眠代替自旋等待,减少CPU占用time.Sleep(time.Millisecond)now=time.Now().UnixMilli()// 处理时间回拨(再次检查)ifnow<s.lastTime{return0,errors.New("time is back, ID generation failed")}s.lastTime=now s.sequence=0}}else{// 新的毫秒,重置序列号s.lastTime=now s.sequence=0}// 生成IDid:=((now-s.epoch)<<timeShift)|(s.workerID<<workerShift)|s.sequencereturnID(id),nil}// ParseID 解析雪花ID// 返回ID的各组成部分:时间戳、工作节点ID、序列号funcParseID(id ID,epochint64)(time.Time,int64,int64){idInt:=int64(id)timestamp:=(idInt>>timeShift)+epoch workerID:=(idInt>>workerShift)&((1<<workerBits)-1)sequence:=idInt&seqMaskreturntime.UnixMilli(timestamp),workerID,sequence}// String 将ID转换为字符串func(id ID)String()string{returnstrconv.FormatInt(int64(id),10)}// Int64 将ID转换为int64func(id ID)Int64()int64{returnint64(id)}
//如何使用sf:=snowflake.New(1)id:=sf.NextID()

3. 雪花算法工程注意点:

  • 时间回拨问题

  • NTP同步导致时间倒退

    解决方案:

  • 禁止自动回拨

  • 检测回拨直接panic/等待

  • 使用逻辑时间

八、如何选?

场景
推荐
单体
DB
小系统/快速上线
Redis
订单/财务流水
Segment
微服务/高并发
雪花算法

友情链接:加班费计算器(vx小程序搜索“加班计”)

*源码地址*

私给


如果您喜欢这篇文章,请您(点赞、分享、亮爱心),万分感谢!

http://www.cnnetsun.cn/news/2036478.html

相关文章:

  • 线性判别分析LDA
  • 保姆级教程:用Image2Lcd和PCtoLCD2002给STM32的OLED屏显示自定义图片(附完整代码)
  • STC8单片机驱动ESP-01S联网实战:从AT指令到GET请求获取苏宁时间(附完整源码)
  • MLOps资源管理优化:从GPU虚拟化到智能调度
  • 手把手教你用LabVIEW驱动Zebra GX420d串口打印机(附完整源码与模板文件)
  • AI与IoT融合:智能边缘计算的应用与挑战
  • 告别链接错误:手把手教你为GCC工具链配置LTO插件(以Nuclei RISC-V GCC 9.2.0为例)
  • 多任务级联CNN:MTCNN人脸检测与关键点对齐全解析
  • PyTorch 2.8镜像惊艳案例:SVD视频生成中运动一致性与画质细节实测
  • 裸金属服务器部署RKE2 Kubernetes集群构建MLOps平台实战
  • 5块钱的2N3819 JFET到手实测:从真假辨别到搭建简易非接触验电笔
  • 初始化联合(union)
  • 030、开源与闭源模型微调生态对比:选择最适合的基座模型
  • Unity 2021.3.8f1 WebGL打包发布到Nginx服务器的完整避坑指南(含Brotli/Gzip配置)
  • 计算机毕业设计:Python股票智能分析与LSTM股价预测平台 Flask框架 LSTM Keras 数据分析 可视化 深度学习 大数据 爬虫(建议收藏)✅
  • 汽车诊断开发避坑指南:ISO14229协议中那些容易忽略的NRC响应规则(附实战代码片段)
  • Less如何优化CSS文件大小_利用压缩配置去除冗余样式
  • 海上目标检测数据集2051张VOC+YOLO
  • 用Python和OpenFAST模拟漂浮式风机:从JONSWAP波浪谱到Morison方程实战
  • 如何解锁8大网盘全速下载:3分钟掌握网盘直链下载助手的完整指南
  • RadiantViewer64bit试用期重置技巧:30天后如何继续免费使用(附详细步骤)
  • 如何快速上手OpenMV IDE:从零开始构建机器视觉项目
  • 从 0 到 1 构建供应链 AI Agent Harness Engineering:需求预测、库存优化与物流调度实战
  • 在Ubuntu 16.04上为全志A40i定制Android 7.1系统镜像:一次完整的构建环境搭建与编译之旅
  • EdgeRemover:彻底告别Windows系统中顽固的Microsoft Edge浏览器
  • 从System.Numerics.Tensors到Microsoft.ML.OnnxRuntime.Managed——.NET原生AI栈的5层性能断层分析(含各层CPU/GPU/内存瓶颈对照表)
  • 告别脚本!Win11 22H2新版WSL2静态IP配置全攻略(含DNS避坑)
  • 【限时技术快照】.NET 11.0.1 RTM补丁发布前最后验证:AI推理Pipeline在Windows/Linux/macOS M3三平台统一加速配置(含完整benchmark对比表)
  • Docker+CANoe+ROS2车载调试闭环构建,深度解析ISO 26262认证环境下的容器安全隔离方案
  • 统一内存编程与OpenACC在HPC中的高效应用