在分布式BASE理论:数据一致性模型有哪些?中,我们谈到了BASE理论的最终一致性,以及简单介绍了数据一致性模型,但我们都是站在一个使用者的角度,在发出数据更新的请求给分布式系统之后,观察返回的数据是否更新。为了更好使用、理解分布式系统,不妨换个视角,观察在服务端是怎么实现一致性的。
因为分布式算法还是比较难的,笔者在这篇文章先对分布式一致性算法的基石——鸽巢原理进行介绍:
- 鸽巢原理
- 鸽巢原理在生活中的应用案例
- 鸽巢原理在计算机领域的应用案例
(若文章有不正之处,或难以理解的地方,请多多谅解,欢迎指正)
鸽巢定理
鸽巢定理,又名抽屉算法,是组合数学里一个重要的原理。
其具体算法是:
-
第一鸽巢原理:如果有n个笼子和n+1只鸽子,所有的鸽子都被关进笼子里,那么至少有一个笼子有至少2只鸽子。
证明(反证法):如果每个笼子里只能放一只鸽子,有n个笼子至多也只能放n只鸽子,而不是题设的n+k(k≥1)只鸽子,故与题设不符。
-
第二鸽巢原理:把m×n+1只鸽子放到n个笼子,所有的鸽子都被关进笼子里,那个至少有一个笼子有m+1只鸽子。
证明(反证法):如果每个笼子里只能放m只鸽子,有n个笼子至多也只能放m×n只鸽子,而不是题设的m×n+1只鸽子,故与题设不符。
-
第三无穷项集鸽巢原理:把无穷多只鸽子放入笼子,则至少有一个笼子里有无穷只鸽子。
这鸽巢定理看着挺好理解的,那么来试做两道题。
鸽巢原理在生活中的应用案例
先来一道生活题热热身。
盒子里有3只黑袜子、2只蓝袜子,你需要拿一对同色的出来,假设只能拿一次,最少需要拿出几只?
其实只要一次拿三只袜子就行了。因为袜子的颜色只有两种(笼子只有2个),一次性拿三只袜子(鸽子有3只),所以至少有一只袜子是同色的。
热身之后,我们再来一道伦理题。
在不丹,某女性有4位丈夫,她一共生了2子3女,那么在什么情况下可以判断,除了4位丈夫,这位女性没有替别的男人生孩子。
笔者列出一种情况:这位女性的孩子中,至少有2位子女来自同一位父亲,且这位女性与每位丈夫都有孩子。那么这4位丈夫还可以稍微松口气,最起码这位女性没给其他男人生孩子。
(这道是开放题,大家可以在评论区说出其他的情况。)
鸽巢原理在计算机领域的应用案例
笔者是后台开发工程师(Java),最近在复习HashMap,发现HashMap的底层结构也运用了鸽巢原理。
我们知道HashMap(JDK1.8)的底层结构是数组+链表/红黑树,如下图所示:
为什么需要数组+链表/红黑树的结构呢?
因为在HashMap实际上也是哈希表,通过哈希表实现数据的分散操作方式为:在插入新值(key, value)的时候,需要将key传入哈希算法中,得到在哈希表存储位置的下标index,最后再将value放入哈希表索引为index的位置。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//AbstractMap
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
所以在插入数据时,是有一定概率发生哈希冲突的,因为Keys的数目总会比哈希表的索引多,总会有两个key在经过哈希算法后,得到相同的index,所以不管是多么高明的算法都不可能解决这个问题。HashMap采用了数组+链表/红黑树的方式,即使发生了哈希冲突,只需将新值放在对应哈希表索引的链表上即可。
结语
看到这里的读者们,相信你们对鸽巢原理也有了一定的理解了,接下来会对鸽巢原理的应用之一——Quorum算法进行介绍。
笔者其实是小菜鸡一只,也没学过组合数学,只是在了解分布式系统的过程中学到鸽巢原理,所以才斗胆写出自己的理解。本文仅代表个人理解,如果若文章有不正之处,或难以理解的地方,请多多谅解,欢迎指正。
如果本文对你的学习有帮助,请给一个赞吧,这会是我最大的动力~
参考资料: