Files
sixGuoDjango/wechat_数据库/雪花算法/雪花算法工具.py
T
2026-08-02 14:07:04 +08:00

71 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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())