雪花ID(Go 实现)

发布时间:2024-12-19 13:01

雪花ID的实现

之前做项目的时候遇到,今天再深入理解一下。

文章目录

  • 雪花ID的实现
  • 前言
  • 一、雪花ID的作用?
  • 二、雪花ID的原理
  • 三、雪花ID的代码实现(Go 语言)
  • 四、雪花ID 的缺点


前言

雪花ID 最由推特开源的一种全局唯一ID 的生成算法,有递增、全局唯一等特性。


一、雪花ID的作用?

  • 全局的唯一性
    对于多台机器,毫秒级生成多条不重复ID
  • 递增性
    生成的雪花ID具有递增型,可以加速查询。
  • 可用性高
    支持多线程,分布式的系统架构

二、雪花ID的原理

  • 最高位是符号位,生成的ID总是正数,所以始终为0.
  • 41 位的时间序列,精确到毫秒级,41位的长度可以使用69年,可以利用这个特性进行排序
  • 设定机器编码的表示,可以支持分布式的系统
  • 12 位的计数编码,可以支持毫秒级多个不同的 ID 生成。

雪花ID(Go 实现)_第1张图片

三、雪花ID的代码实现(Go 语言)

一些有关原理的部分都在代码部分进行注释。
也有一些针对需求对雪花ID 算法的修改

package main

import (
	"fmt"
	"sync"
	"time"
)

// 支持 2 ^ 8 - 1 台机器
//每一个毫秒支持 2 ^ 9 - 1 个不同的id
const (
	workerIdBitsMoveLen 	= uint(8)
	maxWorkerId          	= int64(-1 ^ (-1 << workerIdBitsMoveLen))
	timerIdBitsMoveLen 		= uint(17)
	maxNumId 							= int64(-1 ^ (-1 << 9))
)

// 定义一个woker工作节点所需要的基本参数
type Worker1 struct {
	mu        sync.Mutex // 添加互斥锁 确保并发安全
	workerId 	int64      // 机器编码
	timestamp int64      // 记录时间戳
	number    int64      // 当前毫秒已经生成的id序列号(从0开始累加) 1毫秒内最多生成4096个ID
}

// 初始化ID生成结构体
// workerId 机器的编号
func NewWorker1(workerId int64) *Worker1 {
	if workerId > maxWorkerId {
		panic("workerId 不能大于最大值")
	}
	return &Worker1{workerId: workerId,timestamp: 0, number: 0}
}

// 生成id 的方法用于生成唯一id
func (w *Worker1) GetId() int64 {
	epoch := int64(1613811738) // 设置为去年今天的时间戳...因为位数变了后,几百年都用不完,,实际可以设置上线日期的
	w.mu.Lock()
	defer w.mu.Unlock()
	now := time.Now().UnixMilli() // 获得现在对应的时间戳
	if now < w.timestamp {
		// 当机器出现时钟回拨时报错
		panic("Clock moved backwards.  Refusing to generate id for %d milliseconds")
	}
	if w.timestamp == now {
		w.number++
		if w.number > maxNumId { //此处为最大节点ID,大概是2^9-1 511条,
			for now <= w.timestamp {
				now = time.Now().UnixMilli()
			}
		}
	} else {
		w.number = 0
		w.timestamp = now // 将机器上一次生成ID的时间更新为当前时间
	}
	ID := int64((now-epoch)<< timerIdBitsMoveLen | (w.workerId << workerIdBitsMoveLen) | (w.number))
	return ID
}

func testGetId() {
	worker := NewWorker1(55)
	arr := make([]int64,0 ,100)
	
	for i := 0; i < 100; i++ {
		arr = append(arr, worker.GetId())
	}
	fmt.Printf("%+v\n", arr)
}

func main() {
	testGetId()
}


四、雪花ID 的缺点

比如会产生一些比如机器时间戳回拨导致ID 重复的问题

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号