55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
![]() |
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
|
|||
|
import time
|
|||
|
|
|||
|
|
|||
|
class SnowflakeManager(object):
|
|||
|
"""
|
|||
|
Twitter的雪花算法实现
|
|||
|
"""
|
|||
|
|
|||
|
def __init__(self, start_time=1420041600000):
|
|||
|
self.start_time = start_time / 1000 # 以秒为单位
|
|||
|
self.last_timestamp = -1
|
|||
|
|
|||
|
# 41 bits时间戳
|
|||
|
self.timestamp_shift = 22
|
|||
|
# 10 bits机器编号
|
|||
|
self.machine_id_shift = 12
|
|||
|
# 12 bits序列号
|
|||
|
self.sequence_shift = 0
|
|||
|
|
|||
|
# 41 bits可以表示的最大值,2^41 - 1
|
|||
|
self.max_timestamp = -1 ^ (-1 << self.timestamp_shift)
|
|||
|
# 10 bits可以表示的最大值,2^10 - 1
|
|||
|
self.max_machine_id = -1 ^ (-1 << self.machine_id_shift)
|
|||
|
# 12 bits可以表示的最大值,2^12 - 1
|
|||
|
self.max_sequence = -1 ^ (-1 << self.sequence_shift)
|
|||
|
|
|||
|
# 机器编号和序列号暂时不使用,可以通过参数传入
|
|||
|
self.machine_id = 0
|
|||
|
self.sequence = 0
|
|||
|
|
|||
|
def next_id(self):
|
|||
|
timestamp = int(time.time())
|
|||
|
if timestamp < self.last_timestamp:
|
|||
|
raise ValueError('Current timestamp is less than last timestamp.')
|
|||
|
|
|||
|
if timestamp == self.last_timestamp:
|
|||
|
self.sequence = (self.sequence + 1) & self.max_sequence
|
|||
|
if self.sequence == 0:
|
|||
|
timestamp = self.til_next_millis(self.last_timestamp)
|
|||
|
else:
|
|||
|
self.sequence = 0
|
|||
|
|
|||
|
self.last_timestamp = timestamp
|
|||
|
return ((timestamp - int(self.start_time)) << self.timestamp_shift) | (
|
|||
|
self.machine_id << self.machine_id_shift) | self.sequence
|
|||
|
|
|||
|
def til_next_millis(self, last_timestamp):
|
|||
|
timestamp = int(time.time())
|
|||
|
while timestamp <= last_timestamp:
|
|||
|
timestamp = int(time.time())
|
|||
|
return timestamp
|