大家好,我是Maneshwar。我正在构建git-lrc,一个在每次提交时运行的微型AI代码审查工具。这个项目免费且源码公开在Github上,欢迎给它点个Star,帮助更多开发者发现它,也期待你试用后分享反馈。

真值表、位翻转,这些老生常谈的内容没什么新鲜的。直到我读一篇关于P2P网络的文章时,撞见了“XOR距离”这个词,整个人停住了。

打开网易新闻 查看精彩图片

XOR我懂,距离我也懂。XOR距离?这不是一个概念,这是两个概念套了件风衣假装是一个人。

于是我去认真学了一下它的原理,结果发现这属于那种一旦想通就特别简单、但在想通之前让人莫名恼火的点子。所以这次咱们把它彻底讲清楚。

位、桶,以及节点“邻居”为何与物理位置无关

两个ID之间的XOR距离就是:把它们的位异或在一起,把结果当作一个数字来读。这个数字就是你的“距离”。数字越大,离得越远;数字越小,离得越近。就这样,一句话说完了。

显然这不够过瘾,所以我们从头搭一遍。

XOR到底在干什么

XOR(异或)盯着两个位,只问一个问题:“你俩意见一致吗?”相同的位得到0,不同的位得到1。XOR基本就是计算机科学里的“找不同”运算符。

现在拿两个ID来试。真实系统里这些是160位或256位的哈希,但为了不让人眯着眼看,我们用4位:

A = 1100

B = 1010

XOR结果 = 0110

把0110当作普通二进制数来读,得到6。所以distance(A, B) = 6。恭喜,你刚手动算出了一个XOR距离,可以写进简历了。

为什么它能被叫做“距离”

数学对“距离”这个词很挑剔。一个东西要算作正经度量,需要满足三个性质,而XOR恰好三条全中。这感觉像是个幸运的巧合,但其实不是。

第三个性质是它不只是个可爱数学把戏的根本原因,正是它让路由能够收敛。

最容易把人绕进去的地方

XOR距离不是“数一数有多少位不同”——那是汉明距离,一个不同但用处小得多的表亲。XOR距离关心的是不同位出现在哪里,因为它是被当作数字来读的,而在数字里,最左边的位远比最右边的位重要。

1000 XOR 0000 = 1000 = 8,在最左边(高位)不一致

0000 XOR 0001 = 0001 = 1,在最右边(低位)不一致

这两对都只差一个位。其中一对比另一对“远”了8倍。同样程度的不一致,距离却天差地别,全因为不一致发生的位置不同。

情绪上大概就是这种感觉:同样的分歧,位置不同,分量完全不同。

动手算一算

理论够了,来真的算一下:

def xor_distance(a: int, b: int) -> int: return a ^ b

def bucket_index(distance: int) -> int: 用来判断这个距离落入哪个“桶”

这就是XOR距离的核心:两个ID异或后读出的数字,决定了它们在覆盖网络里的远近。它跟节点实际住在哪个机房、哪个城市没有半点关系,只跟ID的位结构有关。想通这一点,P2P路由里那些“邻居”为什么长那样,就一点都不奇怪了。