雪花算法生成数字id_分布式唯一Id解决方案雪花算法

0b78e74cbfe3fd38ab420a00d2284663.gif

雪花算法

1 关于雪花

雪花(snowflake)在自然界中,是极具独特美丽,又变幻莫测的东西:

  • 1.雪花属于六方晶系,它具有四个结晶轴,其中三个辅轴在一个基面上,互相以60度的角度相交,第四轴(主晶轴)与三个辅轴所形成的基面垂直;

  • 2.雪花的基本形状是六角形,但是大自然中却几乎找不出两朵完全相同的雪花,每一个雪花都拥有自己的独有图案,就象地球上找不出两个完全相同的人一样。许多学者用显微镜观测过成千上万朵雪花,这些研究最后表明,形状、大小完全一样和各部分完全对称的雪花,在自然界中是无法形成的。

2 雪花算法

雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等。

自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景。GUID:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。

42bbae39d8b77ae74d13059130f32b97.png

3 算法描述

  • 最高位是符号位,始终为0,不可用。

  • 41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。

  • 10位的机器标识,10位的长度最多支持部署1024个节点。

  • 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。

代码:

package main

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

const (
workerBits uint8 = 10
numberBits uint8 = 12
workerMax int64 = -1 ^ (-1 << workerBits)
numberMax int64 = -1 ^ (-1 << numberBits)
timeShift uint8 = workerBits + numberBits
workerShift uint8 = numberBits
startTime int64 = 1525705533000 // 如果在程序跑了一段时间修改了epoch这个值 可能会导致生成相同的ID
)

type Worker struct {
mu sync.Mutex
timestamp int64
workerId int64
number int64
}

func NewWorker(workerId int64) (*Worker, error) {
if workerId < 0 || workerId > workerMax {
return nil, errors.New("Worker ID excess of quantity")
}
// 生成一个新节点
return &Worker{
timestamp: 0,
workerId: workerId,
number: 0,
}, nil
}

func (w *Worker) GetId() int64 {
w.mu.Lock()
defer w.mu.Unlock()
now := time.Now().UnixNano() / 1e6
if w.timestamp == now {
w.number++
if w.number > numberMax {
for now <= w.timestamp {
now = time.Now().UnixNano() / 1e6
}
}
} else {
w.number = 0
w.timestamp = now
}
ID := int64((now-startTime)<<timeShift | (w.workerId << workerShift) | (w.number))
return ID
}
func main() {
// 生成节点实例
node, err := NewWorker(1)
if err != nil {
panic(err)
}
for {
fmt.Println(node.GetId())
}
}
5cd1217376e8648aaccb3c0f92fc72f1.png - End - fe726b75863d293573d6618dc3247281.png

好文点赞收藏

635e8adc46f6be682021af68c4cd8b76.png635e8adc46f6be682021af68c4cd8b76.png635e8adc46f6be682021af68c4cd8b76.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值