1 import logging
2 import time
3
4 # 64位ID的划分
5 WORKER_ID_BITS = 3
6 DATACENTER_ID_BITS = 5
7 SEQUENCE_BITS = 12
8
9 # 最大取值计算
10 MAX_WORKER_ID = -1 ^ (-1 << WORKER_ID_BITS) # 2**5-1 0b11111
11 MAX_DATACENTER_ID = -1 ^ (-1 << DATACENTER_ID_BITS)
12
13 # 移位偏移计算
14 WOKER_ID_SHIFT = SEQUENCE_BITS
15 DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
16 TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS
17
18 # 序号循环掩码
19 SEQUENCE_MASK = -1 ^ (-1 << SEQUENCE_BITS)
20
21 # Twitter元年时间戳
22 TWEPOCH = 1288834974657
23
24 logger = logging.getLogger('view.logger')
25
26
27 class IdWorker(object):
28 """
29 用于生成IDs
30 """
31
32 def __init__(self, datacenter_id, worker_id, sequence=0):
33 """
34 初始化
35 :param datacenter_id: 数据中心(机器区域)ID
36 :param worker_id: 机器ID
37 :param sequence: 其实序号
38 """
39 # sanity check
40 if worker_id > MAX_WORKER_ID or worker_id < 0:
41 raise ValueError('worker_id值越界')
42
43 if datacenter_id > MAX_DATACENTER_ID or datacenter_id < 0:
44 raise ValueError('datacenter_id值越界')
45
46 self.worker_id = worker_id
47 self.datacenter_id = datacenter_id
48 self.sequence = sequence
49
50 self.last_timestamp = -1 # 上次计算的时间戳
51
52 def _gen_timestamp(self):
53 """
54 生成整数时间戳
55 :return:int timestamp
56 """
57 return int(time.time() * 1000)
58
59 def get_id(self):
60 """
61 获取新ID
62 :return:
63 """
64 timestamp = self._gen_timestamp()
65
66 # 时钟回拨
67 if timestamp < self.last_timestamp:
68 logger.error('clock is moving backwards. Rejecting requests until{}'.format(self.last_timestamp))
69 raise Exception
70
71 if timestamp == self.last_timestamp:
72 self.sequence = (self.sequence + 1) & SEQUENCE_MASK
73 if self.sequence == 0:
74 timestamp = self._til_next_millis(self.last_timestamp)
75 else:
76 self.sequence = 0
77
78 self.last_timestamp = timestamp
79
80 new_id = ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | (self.datacenter_id << DATACENTER_ID_SHIFT) | (
81 self.worker_id << WOKER_ID_SHIFT) | self.sequence
82
83 return new_id
84
85 def _til_next_millis(self, last_timestamp):
86 """
87 等到下一毫秒
88 """
89 timestamp = self._gen_timestamp()
90 while timestamp <= last_timestamp:
91 timestamp = self._gen_timestamp()
92 return timestamp
93
94
95 __worker = IdWorker(1, 1, 0)
96
97
98 def generate_id():
99 return __worker.get_id()
100
101
102 if __name__ == '__main__':
103 from threading import Thread
104
105
106 def test():
107 for i in range(10):
108 id = worker.get_id()
109 print(id)
110
111
112 worker = IdWorker(1, 1, 0)
113
114 l = list()
115 for i in range(2):
116 t = Thread(target=test)
117 t.start()
118 l.append(t)
119 for t in l:
120 t.join()