3 Star 0 Fork 0

Ander/tools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
snow.go 4.22 KB
一键复制 编辑 原始数据 按行查看 历史
Ander 提交于 2年前 . -add snow getidStr
package helper
import (
"errors"
"fmt"
"strconv"
"sync"
"time"
)
const (
twepoch = int64(1417937700000) // 默认起始的时间戳 1449473700000 。计算时,减去这个值
DistrictIdBits = uint(4) //区域 所占用位置
NodeIdBits = uint(9) //节点 所占位置 2的n次幂,6就是2的6次幂64个节点
sequenceBits = uint(10) //自增ID 所占用位置
/*
* 1 符号位 | 39 时间戳 | 2 区域 | 7 节点 | 8 (毫秒内)自增ID
* 0 | 0000000 00000000 00000000 00000000 00000000 | 00 | 000000 0 | 000000 0000
*
*/
maxNodeId = -1 ^ (-1 << NodeIdBits) //节点 ID 最大范围
maxDistrictId = -1 ^ (-1 << DistrictIdBits) //最大区域范围
nodeIdShift = sequenceBits //左移次数
DistrictIdShift = sequenceBits + NodeIdBits
timestampLeftShift = sequenceBits + NodeIdBits + DistrictIdBits
sequenceMask = -1 ^ (-1 << sequenceBits)
maxNextIdsNum = 100 //单次获取ID的最大数量
)
type IdWorker struct {
sequence int64 //序号
lastTimestamp int64 //最后时间戳
nodeId int64 //节点ID
twepoch int64
districtId int64
mutex sync.Mutex
}
// NewIdWorker 创建雪花算法对象,当前设置为17位id,支持的districtId区域(可理解为IDC机房或云区域)为2的2次幂0-3,共4个区域,NodeId范围是2的7次幂0-127共128个节点数量,8毫秒内自增id
func NewIdWorker(districtId, NodeId int64) (*IdWorker, error) {
idWorker := &IdWorker{}
println(maxNodeId)
if NodeId > maxNodeId || NodeId < 0 {
return nil, errors.New(fmt.Sprintf("NodeId Id: %d error", NodeId))
}
if districtId > maxDistrictId || districtId < 0 {
return nil, errors.New(fmt.Sprintf("District Id: %d error", districtId))
}
idWorker.nodeId = NodeId
idWorker.districtId = districtId
idWorker.lastTimestamp = -1
idWorker.sequence = 0
idWorker.twepoch = twepoch
idWorker.mutex = sync.Mutex{}
return idWorker, nil
}
// timeGen generate a unix millisecond.
func timeGen() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
// tilNextMillis spin wait till next millisecond.
func tilNextMillis(lastTimestamp int64) int64 {
timestamp := timeGen()
for timestamp <= lastTimestamp {
timestamp = timeGen()
}
return timestamp
}
// NextId get a snowflake id.
func (id *IdWorker) NextId() (int64, error) {
id.mutex.Lock()
defer id.mutex.Unlock()
// 默认19位id,获取最后16位,为了解决前端js精度丢失的问题
return id.nextid()
}
// GetId 获取id,当前设置为17位id,支持的区域为2的2次幂4个区域,nodeId范围是2的7次幂0-127共128个节点数量,8毫秒内自增id
func (id *IdWorker) GetId() (id17 int64) {
id.mutex.Lock()
defer id.mutex.Unlock()
id17, _ = id.nextid()
// 默认19位id,获取最后17位,为了解决前端js精度丢失的问题
return
}
// GetIdStr 获取id,当前设置为19位id,支持的区域为2的2次幂4个区域,nodeId范围是2的7次幂0-127共128个节点数量,8毫秒内自增id
func (id *IdWorker) GetIdStr() (idStr string) {
id.mutex.Lock()
defer id.mutex.Unlock()
idInt, _ := id.nextid()
idStr = strconv.FormatInt(idInt, 10)
// 默认19位id,获取最后17位,为了解决前端js精度丢失的问题
return
}
// NextIds get snowflake ids.
func (id *IdWorker) NextIds(num int) ([]int64, error) {
if num > maxNextIdsNum || num < 0 {
return nil, errors.New(fmt.Sprintf("NextIds num: %d error", num))
}
ids := make([]int64, num)
id.mutex.Lock()
defer id.mutex.Unlock()
for i := 0; i < num; i++ {
ids[i], _ = id.nextid()
}
return ids, nil
}
func (id *IdWorker) nextid() (int64, error) {
timestamp := timeGen()
if timestamp < id.lastTimestamp {
return 0, errors.New(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", id.lastTimestamp-timestamp))
}
if id.lastTimestamp == timestamp {
id.sequence = (id.sequence + 1) & sequenceMask
if id.sequence == 0 {
timestamp = tilNextMillis(id.lastTimestamp)
}
} else {
id.sequence = 0
}
id.lastTimestamp = timestamp
return ((timestamp - id.twepoch) << timestampLeftShift) | (id.districtId << DistrictIdShift) | (id.nodeId << nodeIdShift) | id.sequence, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/ander888/tools.git
git@gitee.com:ander888/tools.git
ander888
tools
tools
master

搜索帮助