71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
import threading
|
||||
|
|
import time
|
|||
|
|
|
|||
|
|
|
|||
|
|
class SnowflakeIDGenerator:
|
|||
|
|
# 目标:总比特数约40位,十进制最多12位(2^40 ≈ 1.1e12)
|
|||
|
|
# 时间戳用28位(可覆盖约8.5年),机器ID用6位(64台),序列号用6位(每毫秒64个)
|
|||
|
|
TIMESTAMP_BITS = 28
|
|||
|
|
WORKER_ID_BITS = 6
|
|||
|
|
SEQUENCE_BITS = 6
|
|||
|
|
|
|||
|
|
# 起始时间戳(2025-01-01 00:00:00 UTC),单位毫秒
|
|||
|
|
CUSTOM_EPOCH = 1735689600000
|
|||
|
|
|
|||
|
|
MAX_WORKER_ID = -1 ^ (-1 << WORKER_ID_BITS)
|
|||
|
|
MAX_SEQUENCE = -1 ^ (-1 << SEQUENCE_BITS)
|
|||
|
|
|
|||
|
|
# 移位计算
|
|||
|
|
WORKER_ID_SHIFT = SEQUENCE_BITS
|
|||
|
|
TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
|
|||
|
|
|
|||
|
|
def __init__(self, worker_id, sequence=0):
|
|||
|
|
if worker_id > self.MAX_WORKER_ID or worker_id < 0:
|
|||
|
|
raise ValueError(f"Worker ID must be between 0 and {self.MAX_WORKER_ID}")
|
|||
|
|
self.worker_id = worker_id
|
|||
|
|
self.sequence = sequence
|
|||
|
|
self.last_timestamp = -1
|
|||
|
|
self.lock = threading.Lock()
|
|||
|
|
|
|||
|
|
def _wait_next_ms(self, last_ts):
|
|||
|
|
ts = self._now()
|
|||
|
|
while ts <= last_ts:
|
|||
|
|
ts = self._now()
|
|||
|
|
return ts
|
|||
|
|
|
|||
|
|
def _now(self):
|
|||
|
|
return int(time.time() * 1000)
|
|||
|
|
|
|||
|
|
def generate_id(self):
|
|||
|
|
with self.lock:
|
|||
|
|
ts = self._now()
|
|||
|
|
if ts < self.last_timestamp:
|
|||
|
|
raise Exception("Clock moved backwards")
|
|||
|
|
if ts == self.last_timestamp:
|
|||
|
|
self.sequence = (self.sequence + 1) & self.MAX_SEQUENCE
|
|||
|
|
if self.sequence == 0:
|
|||
|
|
ts = self._wait_next_ms(self.last_timestamp)
|
|||
|
|
else:
|
|||
|
|
self.sequence = 0
|
|||
|
|
self.last_timestamp = ts
|
|||
|
|
|
|||
|
|
# 相对时间(毫秒),只取低TIMESTAMP_BITS位
|
|||
|
|
relative_ts = (ts - self.CUSTOM_EPOCH) & ((1 << self.TIMESTAMP_BITS) - 1)
|
|||
|
|
new_id = (relative_ts << self.TIMESTAMP_SHIFT) | \
|
|||
|
|
(self.worker_id << self.WORKER_ID_SHIFT) | \
|
|||
|
|
self.sequence
|
|||
|
|
return new_id
|
|||
|
|
|
|||
|
|
def generate_str(self):
|
|||
|
|
return str(self.generate_id())
|
|||
|
|
|
|||
|
|
|
|||
|
|
# 全局生成器实例 (worker_id和datacenter_id需在分布式环境中保证唯一)
|
|||
|
|
# 单机开发环境可暂时固定,生产环境建议通过配置中心或启动参数传入
|
|||
|
|
generator = SnowflakeIDGenerator(worker_id=1)
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
print(generator.generate_id())
|
|||
|
|
print(type(generator.generate_id()))
|
|||
|
|
print(generator.generate_str())
|