[go 面试] 雪花算法与分布式ID生成

简介: [go 面试] 雪花算法与分布式ID生成

生成全局唯一ID的雪花算法原理


雪花算法是一种用于生成全局唯一ID的算法,最初由Twitter开发,用于解决分布式系统中生成ID的问题。其核心思想是将一个64位的长整型ID划分成多个部分,每个部分用于表示不同的信息,确保了生成的ID在分布式环境下的唯一性。


ID结构


  1. 符号位(1位):始终为0,用于保证ID为正数。
  2. 时间戳(41位):表示生成ID的时间戳,精确到毫秒级。
  3. 工作节点ID(10位):表示生成ID的机器的唯一标识。
  4. 序列号(12位):表示在同一毫秒内生成的多个ID的序列号。


生成步骤


  1. 获取当前时间戳,精确到毫秒级。
  2. 如果当前时间小于上次生成ID的时间,或者在同一毫秒内生成的ID数量超过最大值,等待下一毫秒再继续生成。
  3. 如果当前时间等于上次生成ID的时间,序列号自增1。
  4. 如果当前时间大于上次生成ID的时间,序列号重新从0开始。
  5. 将各个部分的值组合,得到最终的64位ID。


Go实现雪花算法的高并发ID生成器


package main
import (
 "fmt"
 "sync"
 "time"
)
const (
 workerBits     = 10
 sequenceBits   = 12
 workerMax      = -1 ^ (-1 << workerBits)
 sequenceMask   = -1 ^ (-1 << sequenceBits)
 timeShift      = workerBits + sequenceBits
 workerShift    = sequenceBits
 epoch          = 1609459200000
)
type Snowflake struct {
 mu          sync.Mutex
 lastTime    int64
 workerID    int64
 sequence    int64
}
func NewSnowflake(workerID int64) *Snowflake {
 if workerID < 0 || workerID > workerMax {
  panic(fmt.Sprintf("worker ID must be between 0 and %d", workerMax))
 }
 return &Snowflake{
  lastTime: time.Now().UnixNano() / 1e6,
  workerID: workerID,
  sequence: 0,
 }
}
func (sf *Snowflake) NextID() int64 {
 sf.mu.Lock()
 defer sf.mu.Unlock()
 currentTime := time.Now().UnixNano() / 1e6
 if currentTime < sf.lastTime {
  panic(fmt.Sprintf("clock moved backwards, refusing to generate ID for %d milliseconds", sf.lastTime-currentTime))
 }
 if currentTime == sf.lastTime {
  sf.sequence = (sf.sequence + 1) & sequenceMask
  if sf.sequence == 0 {
   for currentTime <= sf.lastTime {
    currentTime = time.Now().UnixNano() / 1e6
   }
  }
 } else {
  sf.sequence = 0
 }
 sf.lastTime = currentTime
 id := (currentTime-epoch)<<timeShift | (sf.workerID << workerShift) | sf.sequence
 return id
}
func main() {
 sf := NewSnowflake(1) // 假设工作节点ID为1
 for i := 0; i < 10; i++ {
  id := sf.NextID()
  fmt.Println(id)
  time.Sleep(time.Millisecond)
 }
}


高并发下的唯一性和递增性保障


在高并发场景下,保障雪花算法生成的ID唯一性和递增性的关键在于:


  1. 唯一性: 工作节点ID的设置保证了不同节点生成的ID不会冲突。序列号的自增和位运算保证了同一毫秒内生成的ID唯一。
  2. 递增性: 在同一毫秒内生成的多个ID按序列号的递增顺序排列。即使在极端情况下,同一毫秒内生成的ID数量超过了最大值,会等待下一毫秒重新开始,也保证了递增性。


总体来说,雪花算法在高并发下是一个可靠的ID生成方案。它的高性能和低碰撞概率使得它在分布式系统中被广泛应用。

相关文章
|
1天前
|
消息中间件 架构师 Java
阿里面试:秒杀的分布式事务, 是如何设计的?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试阿里、滴滴、极兔等一线互联网企业时,遇到了许多关于分布式事务的重要面试题。为了帮助大家更好地应对这些面试题,尼恩进行了系统化的梳理,详细介绍了Seata和RocketMQ事务消息的结合,以及如何实现强弱结合型事务。文章还提供了分布式事务的标准面试答案,并推荐了《尼恩Java面试宝典PDF》等资源,帮助大家在面试中脱颖而出。
|
11天前
|
算法
基于粒子群算法的分布式电源配电网重构优化matlab仿真
本研究利用粒子群算法(PSO)优化分布式电源配电网重构,通过Matlab仿真验证优化效果,对比重构前后的节点电压、网损、负荷均衡度、电压偏离及线路传输功率,并记录开关状态变化。PSO算法通过迭代更新粒子位置寻找最优解,旨在最小化网络损耗并提升供电可靠性。仿真结果显示优化后各项指标均有显著改善。
|
1月前
|
NoSQL Java Redis
面试官:项目中如何实现分布式锁?
面试官:项目中如何实现分布式锁?
76 6
面试官:项目中如何实现分布式锁?
|
13天前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
33 2
|
10天前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!
|
2月前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
2月前
|
SQL 算法 Serverless
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
21 1
|
2月前
|
算法 NoSQL 中间件
go语言后端开发学习(六) ——基于雪花算法生成用户ID
本文介绍了分布式ID生成中的Snowflake(雪花)算法。为解决用户ID安全性与唯一性问题,Snowflake算法生成的ID具备全局唯一性、递增性、高可用性和高性能性等特点。64位ID由符号位(固定为0)、41位时间戳、10位标识位(含数据中心与机器ID)及12位序列号组成。面对ID重复风险,可通过预分配、动态或统一分配标识位解决。Go语言实现示例展示了如何使用第三方包`sonyflake`生成ID,确保不同节点产生的ID始终唯一。
go语言后端开发学习(六) ——基于雪花算法生成用户ID
|
2月前
|
Go API 数据库
[go 面试] 分布式事务框架选择与实践
[go 面试] 分布式事务框架选择与实践
|
2月前
|
存储 算法 数据挖掘
技术分享:从雪花算法生成订单ID的抉择与反思
【8月更文挑战第17天】在软件开发的浩瀚征途中,技术选型如同航海中的罗盘,指引着项目前进的方向。今天,我想与大家分享一段关于“用雪花算法生成订单ID,现在我有点后悔了”的亲身经历,希望通过这段故事,为大家在技术选型时提供一些参考与启示。
76 0

热门文章

最新文章