| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 | 
							- package setting
 
- import (
 
- 	"errors"
 
- 	"fmt"
 
- 	"sync"
 
- 	"time"
 
- )
 
- const (
 
- 	twepoch        = int64(1417937700000) // 默认起始的时间戳 1449473700000 。计算时,减去这个值
 
- 	DistrictIdBits = uint(5)              //区域 所占用位置
 
- 	NodeIdBits     = uint(9)              //节点 所占位置
 
- 	sequenceBits   = uint(10)             //自增ID 所占用位置
 
- 	/*
 
- 	 * 1 符号位  |  39 时间戳                                     | 5 区域  |  9 节点       | 10 (毫秒内)自增ID
 
- 	 * 0        |  0000000 00000000 00000000 00000000 00000000  | 00000  | 000000 000   |  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 new a snowflake id generator object.
 
- func NewIdWorker(NodeId int64) (*IdWorker, error) {
 
- 	var districtId int64
 
- 	districtId = 1 //暂时默认给1 ,方便以后扩展
 
- 	idWorker := &IdWorker{}
 
- 	if NodeId > maxNodeId || NodeId < 0 {
 
- 		fmt.Sprintf("NodeId Id can't be greater than %d or less than 0", maxNodeId)
 
- 		return nil, errors.New(fmt.Sprintf("NodeId Id: %d error", NodeId))
 
- 	}
 
- 	if districtId > maxDistrictId || districtId < 0 {
 
- 		fmt.Sprintf("District Id can't be greater than %d or less than 0", maxDistrictId)
 
- 		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{}
 
- 	fmt.Sprintf("worker starting. timestamp left shift %d, District id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, DistrictIdBits, NodeIdBits, sequenceBits, NodeId)
 
- 	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()
 
- 	return id.nextid()
 
- }
 
- // NextIds get snowflake ids.
 
- func (id *IdWorker) NextIds(num int) ([]int64, error) {
 
- 	if num > maxNextIdsNum || num < 0 {
 
- 		fmt.Sprintf("NextIds num can't be greater than %d or less than 0", maxNextIdsNum)
 
- 		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()
 
- 	//id.lastTimestamp 最后的时间戳
 
- 	if timestamp < id.lastTimestamp {
 
- 		//    fmt.Sprintf("clock is moving backwards.  Rejecting requests until %d.", 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 {
 
- 		// sequence 序号
 
- 		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
 
- }
 
 
  |