• 雪花算法(snowflake)python简易实现


      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()
  • 相关阅读:
    交换函数作业
    对本课程的期望及对老师的建议
    前一半元素与后一半元素交换
    使用多线程(newSingleThreadScheduledExecutor)创建一个定时任务
    js判断是否为整数
    kafka入门及使用(不用集成spring)
    Eclipse 必须安装的几个插件
    mybatis 批量插入/批量修改的写法
    maven pom.xml中出现错误failOnMissingWebXml Dynamic Web Module 3.1 requires Java 1.7 or newer,每次update后都会回滚到1.5解决方案
    Eclipse 插件安装及相关问题解决方案(svn、spring、gradle、git)
  • 原文地址:https://www.cnblogs.com/wangwei916797941/p/16362942.html
Copyright © 2020-2023  润新知