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())
|