雪花算法-go实现
雪花算法能高性能地生成有序的唯一id,解决一些分布式服务中生成全局唯一id的需求。本章是该github的go实现版。
一:概念
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
id的结构组成:64位 = 1未使用 + 41 毫秒时间戳 + 5 datacenterid + 5 workerid + 12 毫秒级的计数「每毫秒可以生成4096个id序号」
注:datacenterid的5位也可以直接舍弃掉,分配10个workerid。
二:代码
snowflake.go
package main import ( "errors" "time" ) var startStamp int64 = 1588829612000 //当前时间戳 var sequenceBit int64 = 12 // 序列占位数 var machineBit int64 = 5 // 机器id占位数 var dataCenterBit int64 = 5 // 数据中心id占位数 var maxDataCenterNum int64 = -1 ^ (-1 << dataCenterBit) // 数据中心id最大值 var maxMachineNum int64 = -1 ^ (-1 << machineBit) // 机器id最大值 var maxSequence int64 = -1 ^ (-1 << sequenceBit) // 序列最大值 var machineLeft = sequenceBit // 机器id左移位数 var dataCenterLeft = sequenceBit + machineBit // 数据中心id左移位数 var timestampLeft = dataCenterBit + dataCenterLeft // 时间戳左移位数 var sequence int64 = 0 // 同一毫秒序列 var lastStmp int64 = -1 // 上一个毫秒戳 type SnowFlake struct { dataCenterId, machineId int64 } /** 获取下个uuid */ func (snowFlake SnowFlake) getNextId() (int64, error) { var currStmp = getNewstamp() if currStmp < lastStmp { return 0, errors.New("时间不可倒退,bro") } if currStmp == lastStmp { sequence = (sequence + 1) & maxSequence if sequence == 0 { currStmp = getNextMill() } } else { sequence = 0 } lastStmp = currStmp return (currStmp-startStamp)<<timestampLeft | snowFlake.dataCenterId<<dataCenterLeft | snowFlake.machineId<<machineLeft | sequence, nil } /** 获取比当前时间戳更新的时间戳 */ func getNextMill() int64 { var mill = getNewstamp() for mill <= lastStmp { mill = getNewstamp() } return mill } /** 获取当前毫秒时间戳 */ func getNewstamp() int64 { return time.Now().UnixNano() / 1e6 }
main.go
package main import ( "fmt" "time" ) func main() { var dataCenterId int64 = 2 var machineId int64 = 3 start := time.Now() snowFlake := SnowFlake{dataCenterId, machineId} for i := 0; i < 1000000; i++ { snowFlake.getNextId() } fmt.Println(time.Since(start)) }
三 :效率
单机上,6c12t,100w数据用了200ms