Blame view

utils/snowflake.go 2.63 KB
ee23102d   zhangqijia   支持mongo, grpc接服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  package utils
  
  import (
  	"fmt"
  	"github.com/golang/glog"
  	"sync"
  	"time"
  )
  
  type Snowflake struct {
  	*sync.Mutex					// 锁
  	timestamp    int64	// 时间戳 ,毫秒
  	workerid     int64  // 工作节点
  	datacenterid int64	// 数据中心机房id
  	sequence     int64	// 序列号
  }
  const (
  	epoch             = int64(1577808000000)                           // 设置起始时间(时间戳/毫秒):2020-01-01 00:00:00,有效期69年
  	timestampBits     = uint(41)                                       // 时间戳占用位数
  	datacenteridBits  = uint(2)                                        // 数据中心id所占位数
  	workeridBits      = uint(7)                                        // 机器id所占位数
  	sequenceBits      = uint(12)                                       // 序列所占的位数
  	timestampMax      = int64(-1 ^ (-1 << timestampBits))              // 时间戳最大值
  	datacenteridMax   = int64(-1 ^ (-1 << datacenteridBits))           // 支持的最大数据中心id数量
  	workeridMax       = int64(-1 ^ (-1 << workeridBits))               // 支持的最大机器id数量
  	sequenceMask      = int64(-1 ^ (-1 << sequenceBits))               // 支持的最大序列id数量
  	workeridShift     = sequenceBits                                   // 机器id左移位数
  	datacenteridShift = sequenceBits + workeridBits                    // 数据中心id左移位数
  	timestampShift    = sequenceBits + workeridBits + datacenteridBits // 时间戳左移位数
  )
  
  
  
  func NewSnowflake(workerid, datacenterid int64) *Snowflake {
  	return &Snowflake{
  		Mutex:        new(sync.Mutex),
  		timestamp:    time.Now().UnixNano() / 1000000,
  		workerid:     workerid,
  		datacenterid: datacenterid,
  		sequence:     0,
  	}
  }
  
  func (s *Snowflake) NextValStr() string {
  	return fmt.Sprintf("%d", s.NextVal())
  }
  
  
  func (s *Snowflake) NextVal() int64 {
  	s.Lock()
  	now := time.Now().UnixNano() / 1000000 // 转毫秒
  	if s.timestamp == now {
  		// 当同一时间戳(精度:毫秒)下多次生成id会增加序列号
  		s.sequence = (s.sequence + 1) & sequenceMask
  		if s.sequence == 0 {
  			// 如果当前序列超出12bit长度,则需要等待下一毫秒
  			// 下一毫秒将使用sequence:0
  			for now <= s.timestamp {
  				now = time.Now().UnixNano() / 1000000
  			}
  		}
  	} else {
  		// 不同时间戳(精度:毫秒)下直接使用序列号:0
  		s.sequence = 0
  	}
  	t := now - epoch
  	if t > timestampMax {
  		s.Unlock()
  		glog.Errorf("epoch must be between 0 and %d", timestampMax-1)
  		return 0
  	}
  	s.timestamp = now
  	r := int64((t)<<timestampShift | (s.datacenterid << datacenteridShift) | (s.workerid << workeridShift) | (s.sequence))
  	s.Unlock()
  	return r
  }