_潜行者

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  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()

 

posted on 2022-06-10 13:40  _潜行者  阅读(933)  评论(0编辑  收藏  举报