如何基于两个64位ID生成唯一且无序的较短ID?
如何基于两个64位唯一ID生成短且无序的唯一ID?
我有两个唯一的64位ID:
ID1 = 677313095844233279 ID2 = 863850283313922058
需要基于这两个ID生成第三个唯一ID,核心要求是**(ID1, ID2)与(ID2, ID1)生成的ID完全一致**。我尝试了两种方法,但都有问题:
比特位合并法:
>>> (ID1 << 64) | ID2 12494221336810479773180694257709350922生成的数值过长,且交换ID顺序后结果完全不同,不满足无序性要求。
frozenset哈希法:
>>> hash(frozenset({ID1, ID2})) -4995465307261022717数值长度合适,但不清楚底层逻辑,想知道生成这类ID的最优算法是什么?
最优方案推荐
核心需求拆解:无序性(输入顺序不影响结果)、唯一性(不同ID对对应不同结果)、短长度(优先64位整数)。以下是不同场景下的最优选择:
1. 最简实现(非跨环境场景)
先对两个ID排序,再用Python内置哈希处理排序后的元组:
def get_unordered_id(a, b): sorted_ids = tuple(sorted((a, b))) return hash(sorted_ids)
- 逻辑清晰:排序保证输入顺序不影响结果,元组哈希是Python内置的稳定实现(同进程内)。
- 结果长度:64位整数,满足“短”的要求。
2. 跨环境稳定实现(低碰撞概率)
如果需要不同Python版本/进程下结果一致,用加密哈希函数处理排序后的ID对,截断为64位整数:
import hashlib def get_unordered_id(a, b): if a > b: a, b = b, a # 将ID转为字符串拼接后哈希,取前8字节转为64位无符号整数 input_str = f"{a}:{b}".encode('utf-8') hash_digest = hashlib.sha256(input_str).digest() return int.from_bytes(hash_digest[:8], byteorder='big', signed=False)
- 稳定性:SHA-256是标准加密哈希,跨环境结果完全一致。
- 碰撞概率:SHA-256的碰撞概率极低,对于大部分业务场景可以忽略。
- 结果长度:64位无符号整数,数值范围在0~1.8e19之间,长度适中。
3. 绝对无碰撞实现(超高唯一性要求)
如果完全不能接受哈希碰撞的风险,排序后合并为128位整数:
def get_unordered_id(a, b): min_id, max_id = min(a, b), max(a, b) return (min_id << 64) | max_id
- 绝对唯一:每个不同的ID对对应唯一的128位整数,无任何碰撞可能。
- 缺点:数值长度为128位,比64位长,但在支持大整数的语言(如Python)中完全可以处理。
关于frozenset哈希的底层说明
你使用的hash(frozenset({ID1, ID2})),其底层逻辑是:集合的哈希值通过遍历所有元素,将当前哈希值与元素哈希值进行异或、移位等组合运算得到。因为集合是无序的,元素遍历顺序不影响最终结果,所以天然满足无序性要求。
但这种方法的问题是非确定性:Python启动时会给内置哈希函数添加随机盐,同一个frozenset在不同进程或Python版本下的哈希值可能不同,不适合需要跨环境一致的场景。
内容的提问来源于stack exchange,提问作者BENJAMIN GILBERT
相关产品推荐
相关产品推荐

