雪花演算法(GO語言版本)
/**
* 時間戳占41 bit 機器ID(機房ID和機器ID)6 bit 毫秒內產生的ID數 16 bit
* 1 23456781234567812345678123456781234567812 345681 2345567812345678
* 雪花演算法
*/
const (
//初始化時間值 2^41 - 1 差不多可以用69年
TimeInitValue = 1585644268888
//機器ID
machineIdBits = 4
//機房ID
computerRoomIdBits = 2
//每毫秒產生的ID數
sequenceBits = 6
)
var (
LastTimestamp = -1
Lock sync.Mutex
)
type IdWork struct {
//機器ID
WorkerId int
//機房ID
DatacenterId int
//代表一毫秒內生成的多個id的最新序號 最多12位 共 4096 -1 = 4095 個id
Sequence int
}
//構造基礎資訊
func NewIdWork(workId, dataId, seq int) *IdWork {
return &IdWork{
WorkerId: workId,
DatacenterId: dataId,
Sequence: seq,
}
}
func getCurrentTime() int {
return int(time.Now().Unix())
}
func tilNextMillis(lastStamp int) int {
for{
timeStamp :=getCurrentTime()
if timeStamp >lastStamp{
return timeStamp
}
}
}
func (id IdWork) nexId() (*int, error) {
Lock.Lock()
defer Lock.Unlock()
workerIdShift := sequenceBits
datacenterIdShift := sequenceBits + machineIdBits
timestampLeftShift := sequenceBits + machineIdBits + computerRoomIdBits
sequenceMask := (1 << sequenceBits) - 1
timeStamp := getCurrentTime()
if timeStamp < LastTimestamp {
return nil, errors.New("系統時鐘發生倒退,生成ID例外,請仔細檢查,")
}
//如果兩個時間相同,則自增一
if LastTimestamp == timeStamp {
id.Sequence = (id.Sequence + 1) & sequenceMask
//當某一毫秒的時間,產生的id數 超過4095,系統會進入等待,直到下一毫秒,系統繼續產生ID
if id.Sequence == 0 {
timeStamp = tilNextMillis(LastTimestamp)
}
} else {
id.Sequence = 0
}
//記錄最后一次產生的時間戳
LastTimestamp = timeStamp
num:=((timeStamp - TimeInitValue) << timestampLeftShift) | (id.DatacenterId << datacenterIdShift) | (id.WorkerId << workerIdShift) | id.Sequence
return &num, nil
}
func main() {
id:=NewIdWork(1,1,1)
for i:=0;i<100;i++{
num,err:=id.nexId()
if err!=nil{
fmt.Println(err.Error())
continue
}
fmt.Printf("當前%d產生演算法ID:%d \n",i,num)
}
}
注釋
- WorkerId (機器ID)
- DatacenterId (機房ID)
- Sequence (代表一毫秒內生成的多個id的最新序號 最多12位 共4095 個id)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/257842.html
標籤:區塊鏈
下一篇:簡單呼叫部署在鏈上的合約
