Go实现雪花算法(snowflake)

什么是雪花算法(snowflake)?

SnowFlake算法是Twitter公司推出,用来在一个分布式的环境中,生成分布式自增且不重复id的算法。

该ID由一个64位二进制数组成,如上图。

  • 第一位 bit 不用,因为二进制中,最高位为1的是负数,而ID是整数,所以不用为0
  • 后面的41位 bit 是产生该ID的毫秒级时间戳,41位毫秒即 2^41/(1000*3600*24*365) ≈ 69,可以用69年
  • 10bit 机器编号,即2^8=1024,最多可以部署在 1024 台机器上
  • 12bit 序列号,2^12=4096,即同一毫秒内最多可以产生 4096 个序列号

 算法实现的思路如上图

将 时间戳左移22位,机器编号左移12位,序列号在最右侧不需要移动,再将3者按位或运算 |,得到一个 64 位二进制数,再将其转换为10进制数,即所需的雪花 ID 

( 位或运算 | 的逻辑是只要两者中有1个数字是1,则结果为1,只有两者都是0时,结果才是0 )

实现代码如下:


const (
	timeLeft     = 22            // 时间戳左移的位数
	machineLeft  = 12            // 机器序号左移的位数
	maxWorkID    = 4095          // 每一毫秒内最大的工作id
	maxMachineID = 1023          // 最大的机器编号
    // 开始时间,2023-01-01 00:00:00的毫秒时间戳, 运行一段时间后如果修改该值可能导致生成重复id
	startTime    = 1672502400000 // 
)

type snowflake struct {
	seq       int64 // 步进号,每生成1个id自增1
	timeStamp int64 // 当前生成id的时间戳
	machineId int64 // 机器编号,范围只能在 [0:1024)
	mu        sync.Mutex
}

// NewSnowflake 输入机器编号,创建新的雪花算法
func NewSnowflake(id int64) (*snowflake, error) {
	if id < 0 || id > maxMachineID {
		return nil, fmt.Errorf("illegal machineID, the range should be between 0 and 1023")
	}

	return &snowflake{
		//timeStamp: getNowLeftTime(),
		timeStamp: time.Now().UnixNano() / 1e6,
		machineId: id,
	}, nil
}

// GetID 获取新的雪花id
func (s *snowflake) GetID() int64 {
	s.mu.Lock()
	defer s.mu.Unlock()

	var id int64
	curTime := time.Now().UnixNano() / 1e6

	// 新生成的雪花id时间戳必须大于等于当前时间的时间戳
	if s.timeStamp < curTime {
		s.timeStamp = curTime
		s.seq = 0
	}

	// 当前时间戳生成的雪花id已经达到最大数值后,必须进入下一毫秒才能继续生成
	if s.seq > maxWorkID {
		time.Sleep(time.Millisecond)
		s.timeStamp = time.Now().UnixNano() / 1e6
		s.seq = 0
	}
	id = ((s.timeStamp - startTime) << timeLeft) | (s.machineId << machineLeft) | s.seq
	s.seq++
	return id
}
// 测试
func main() {
	s, _ := NewSnowflake(1)
	ch := make(chan int64, 1000)
	for i := 0; i < 100; i++ {
		go func() {
			for {
				ch <- s.GetID()
			}
		}()
	}
	i := 0
	for v := range ch {
		i++
		fmt.Println(v) // 输出的结果均为有序
		if i == 1000 {
			close(ch)
			return
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值