Pythonuuid与唯一标识 Python uuid 与唯一标识uuid 模块生成统一唯一标识符 (UUID), 有多种版本满足不同场景。1. uuid1 — 基于时间的 UUID-----------------------------import uuid# UUID1: 基于当前时间戳 节点(MAC地址) 时钟序列# 优势: 时间有序, 可追踪生成时间# 劣势: 会暴露 MAC 地址 (隐私问题)u1 uuid.uuid1()print(UUID1:, u1)print(UUID1 十六进制:, u1.hex) # 32 字符十六进制print(UUID1 版本:, u1.version) # 1# UUID1 字段解析print(时间戳字段:, u1.time) # 100纳秒为单位的时间戳print(时钟序列:, u1.clock_seq) # 时钟序列 (14位)print(节点(MAC):, u1.node) # 48位 MAC 地址# 自定义节点: 避免暴露真实 MAC 地址custom_node 0x123456789ABCu1_custom uuid.uuid1(nodecustom_node)print(自定义节点 UUID1:, u1_custom)# 自定义时钟序列u1_clock uuid.uuid1(clock_seq0x3FFF) # 时钟序列范围 0-0x3FFFprint(自定义时钟 UUID1:, u1_clock)# 从 UUID1 提取时间from datetime import datetime, timezonetime_100ns u1.time - 0x01b21dd213814000 # UUID1 时间的偏移量timestamp_sec time_100ns / 10000000dt datetime.fromtimestamp(timestamp_sec, tztimezone.utc)print(UUID1 生成时间 (UTC):, dt)2. uuid4 — 随机 UUID----------------------import uuid# UUID4: 完全随机生成 (122位随机数 6位版本/变体位)# 优势: 无隐私泄露, 适合大多数应用场景# 劣势: 无序, 数据库索引性能稍差u4 uuid.uuid4()print(UUID4:, u4)print(UUID4 版本:, u4.version) # 4print(UUID4 字节:, u4.bytes) # 16字节原始数据print(UUID4 整数表示:, u4.int) # 128位整数# 生成批量 UUID (列表推导式)batch [uuid.uuid4() for _ in range(5)]print(批量 UUID4:)for i, uid in enumerate(batch):print(f {i1}: {uid})# UUID4 碰撞概率: 极其微小# 每秒生成 10 亿个 UUID4, 约 100 年后才可能发生一次碰撞# 公式: 碰撞概率 ~ n^2 / (2 * 2^122)3. uuid3 / uuid5 — 基于名称的 UUID--------------------------------------import uuid# UUID3: 基于命名空间 名称的 MD5 哈希 (128位)# UUID5: 基于命名空间 名称的 SHA-1 哈希 (128位)# 预定义命名空间:# NAMESPACE_DNS — 域名# NAMESPACE_URL — URL# NAMESPACE_OID — ISO OID# NAMESPACE_X500 — X.500 DN# UUID5: SHA-1 版 (推荐)ns_dns uuid.NAMESPACE_DNSu5_domain uuid.uuid5(ns_dns, example.com)print(UUID5 (DNS):, u5_domain) # 对 example.com 的一致 UUID# 同一名称在同一命名空间下总是生成相同 UUIDu5_domain2 uuid.uuid5(ns_dns, example.com)print(UUID5 相同:, u5_domain u5_domain2) # True# UUID3: MD5 版 (兼容旧系统)u3_domain uuid.uuid3(ns_dns, example.com)print(UUID3 (DNS):, u3_domain)print(UUID3 长度:, len(u3_domain.hex)) # 32# 不同命名空间下相同名称不同结果u5_url uuid.uuid5(uuid.NAMESPACE_URL, example.com)print(UUID5 (URL):, u5_url) # 与 DNS 版不同# 实用场景: 为资源生成确定性 UUIDdef resource_uuid(resource_type, resource_id):为资源生成稳定的 UUID5 标识ns uuid.uuid5(uuid.NAMESPACE_DNS, myapp.example.com)return uuid.uuid5(ns, f{resource_type}:{resource_id})user_uuid resource_uuid(user, alice)post_uuid resource_uuid(post, 12345)print(用户 UUID:, user_uuid)print(文章 UUID:, post_uuid)4. UUID 对象字段与操作-------------------------import uuidu uuid.uuid4()# 基本字段print(UUID 字符串:, str(u)) # 标准格式: 8-4-4-4-12print(UUID hex:, u.hex) # 32字符十六进制print(UUID 字节:, u.bytes) # 16字节 (bytes)print(UUID 字节序 LE:, u.bytes_le) # 混合字节序 (小端 time 域)print(UUID int:, u.int) # 128位整数表示print(UUID 变体:, u.variant) # RFC 4122print(UUID 版本:, u.version) # 4# UUID 比较和排序u1 uuid.uuid4()u2 uuid.uuid4()print(u1 u2:, u1 u2) # 按整数值比较print(相等判断:, u1 u1) # True# 从不同格式创建 UUIDu_from_hex uuid.UUID(hex550e8400e29b41d4a716446655440000)u_from_bytes uuid.UUID(bytesb\x55\x0e\x84\x00\xe2\x9b\x41\xd4\xa7\x16\x44\x66\x55\x44\x00\x00)u_from_int uuid.UUID(int0x550e8400e29b41d4a716446655440000)print(从 hex 创建:, u_from_hex)print(从 bytes 创建:, u_from_bytes)print(从 int 创建:, u_from_int)# UUID 的不可变性u_frozen uuid.uuid4()# u_frozen.int 123 # 会报错! UUID 不可变# 将 UUID 用于字典键cache {uuid.uuid4(): value1, uuid.uuid4(): value2}print(UUID 作为字典键:, len(cache))5. UUID 与数据库主键策略----------------------------import uuid# 场景: 使用 UUID 作为分布式数据库主键# 优势: 全局唯一, 无需中心化序列, 安全 (不暴露数据量)# 劣势: 16字节 vs 4字节 int, 索引效率较低# 策略1: 直接用 UUID 字符串class ModelWithUUID:def __init__(self, name: str):self.id uuid.uuid4()self.name namedef to_db(self):存储到数据库: UUID 转 hex 或 bytesreturn {id_hex: self.id.hex, # 32 字符字符串id_bytes: self.id.bytes, # 16 字节 (需 BINARY(16) 类型)id_str: str(self.id), # 36 字符字符串}entity ModelWithUUID(测试数据)print(数据库存储准备:, entity.to_db())# 策略2: 有序 UUID (类似 UUID1 但更安全)# 可结合时间戳 随机数自行生成有序 UUIDimport timeimport randomdef ordered_uuid():生成时间有序的 UUID (类似 UUID7 方案)# 自定义: 毫秒时间戳(高48位) 随机数(低80位)timestamp_ms int(time.time() * 1000)rand_bits random.getrandbits(80)# 组合成 128 位 UUIDvalue (timestamp_ms 80) | rand_bits# 设置版本位 (4) 和变体位value ~(0xC000 64) # 清除变体位value | 0x8000 64 # 设置变体 (RFC 4122)value ~(0xF000 76) # 清除版本位value | 4 76 # 设置版本 4return uuid.UUID(intvalue)print(有序 UUID:, ordered_uuid())# 策略3: PostgreSQL 的 uuid-ossp 扩展兼容# PSQL: CREATE EXTENSION uuid-ossp;# uuid_generate_v4() - UUID 类型列6. Snowflake ID 模式-------------------------import timeimport threadingclass SnowflakeGenerator:简易雪花 ID 生成器 (64位整数, 非 UUID)def __init__(self, worker_id: int, datacenter_id: int, sequence: int 0):self.worker_id worker_id 0x1F # 5位 工作节点IDself.datacenter_id datacenter_id 0x1F # 5位 数据中心IDself.sequence sequence 0xFFF # 12位 序列号self.tw_epoch 1609459200000 # 自定义纪元 (2021-01-01)self.last_timestamp -1self.lock threading.Lock()def _current_millis(self) - int:return int(time.time() * 1000)def _wait_next_millis(self, last_ts: int) - int:ts self._current_millis()while ts last_ts:ts self._current_millis()return tsdef next_id(self) - int:生成下一个 64 位雪花 IDwith self.lock:timestamp self._current_millis()# 时钟回拨处理 (简化版, 仅等待)if timestamp self.last_timestamp:timestamp self._wait_next_millis(self.last_timestamp)if timestamp self.last_timestamp:self.sequence (self.sequence 1) 0xFFFif self.sequence 0: # 序列号用完timestamp self._wait_next_millis(self.last_timestamp)else:self.sequence 0self.last_timestamp timestamp# 组合: 时间戳(41位) 数据中心(5位) 工作节点(5位) 序列号(12位)snowflake_id (((timestamp - self.tw_epoch) 22) |(self.datacenter_id 17) |(self.worker_id 12) |self.sequence)return snowflake_iddef parse(self, snowflake_id: int) - dict:解析雪花 ID 中的各字段sequence snowflake_id 0xFFFworker_id (snowflake_id 12) 0x1Fdatacenter_id (snowflake_id 17) 0x1Ftimestamp (snowflake_id 22) self.tw_epochreturn {id: snowflake_id,timestamp_ms: timestamp,datacenter_id: datacenter_id,worker_id: worker_id,sequence: sequence,}# 测试雪花 IDsnowflake SnowflakeGenerator(worker_id1, datacenter_id0)ids [snowflake.next_id() for _ in range(3)]print(雪花 ID 列表:, ids)for sid in ids:info snowflake.parse(sid)dt datetime.fromtimestamp(info[timestamp_ms] / 1000, tztimezone.utc)print(f ID{sid}, 时间{dt}, 数据中心{info[datacenter_id]}, 节点{info[worker_id]}, 序列{info[sequence]})7. UUID 的转换与编码-----------------------import uuid# UUID 转不同格式u uuid.uuid4()# 标准 36 字符格式print(标准格式:, str(u)) # xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx# 32 字符十六进制 (不带连字符)print(Hex 格式:, u.hex) # 32 字符# 16 字节 (二进制紧凑格式)print(Bytes 格式:, u.bytes) # 16 字节# Base64 编码 (更紧凑的字符串表示, 22 字符)import base64base64_str base64.urlsafe_b64encode(u.bytes).rstrip(b).decode()print(Base64 格式:, base64_str) # 22 字符# Base64 解码回 UUIDdecoded_bytes base64.urlsafe_b64decode(base64_str )restored_uuid uuid.UUID(bytesdecoded_bytes)print(恢复 UUID:, restored_uuid)print(一致?, u restored_uuid)# 短 UUID 方案: Base62 编码BASE62 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzdef uuid_to_base62(uid: uuid.UUID) - str:将 UUID 编码为 Base62 字符串 (约 22 字符)num uid.intif num 0:return BASE62[0]result []while num 0:result.append(BASE62[num % 62])num // 62return .join(reversed(result))short_id uuid_to_base62(u)print(Base62 短 ID:, short_id)print(长度:, len(short_id)) # 约 22 字符总结: uuid4 最适合通用场景; uuid5 用于确定性标识; uuid1 用于时间有序; 雪花 ID 适合高性能分布式系统.