File size: 2,306 Bytes
8ecfce3 |
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 |
import time
import threading
class Snowflake:
"""
生成随机ID作为时尚行人名字
TODO: 参考:
"""
def __init__(self, datacenter_id=0, worker_id=0):
self.datacenter_id = datacenter_id
self.worker_id = worker_id
self.sequence = 0
self.lock = threading.Lock()
# Twitter的Snowflake算法起始时间戳(2014-01-01)
self.twepoch = 1388534400000
self.worker_id_bits = 5
self.datacenter_id_bits = 5
self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)
self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)
self.sequence_bits = 12
self.worker_id_shift = self.sequence_bits
self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits
self.timestamp_left_shift = self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits
self.sequence_mask = -1 ^ (-1 << self.sequence_bits)
self.last_timestamp = -1
def _til_next_millis(self, last_timestamp):
timestamp = time.time_ns() // 1000000 # 转换为毫秒
while timestamp <= last_timestamp:
timestamp = time.time_ns() // 1000000
return timestamp
def _next_id(self):
with self.lock:
timestamp = time.time_ns() // 1000000
if self.last_timestamp == timestamp:
self.sequence = (self.sequence + 1) & self.sequence_mask
if self.sequence == 0:
timestamp = self._til_next_millis(self.last_timestamp)
else:
self.sequence = 0
if timestamp < self.last_timestamp:
raise Exception("Clock moved backwards. Refusing to generate id for %d milliseconds" % (
self.last_timestamp - timestamp))
self.last_timestamp = timestamp
return ((timestamp - self.twepoch) << self.timestamp_left_shift) | \
(self.datacenter_id << self.datacenter_id_shift) | \
(self.worker_id << self.worker_id_shift) | \
self.sequence
def generate(self):
return self._next_id()
if __name__ == "__main__":
snowflake = Snowflake(datacenter_id=1, worker_id=3)
for i in range(10):
print(snowflake.generate())
|