当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题:

如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少。

Hash 取模

随机放置就不说了,会带来很多问题。通常最容易想到的方案就是 hash 取模了。

可以将传入的 Key 按照 index = hash(key) % N 这样来计算出需要存放的节点。其中 hash 函数是一个将字符串转换为正整数的哈希映射方法,N 就是节点的数量。

这样可以满足数据的均匀分配,但是这个算法的容错性和扩展性都较差。

比如增加或删除了一个节点时,所有的 Key 都需要重新计算,显然这样成本较高,为此需要一个算法满足分布均匀同时也要有良好的容错性和拓展性。

一致 Hash 算法

一致 Hash 算法是将所有的哈希值构成了一个环,其范围在 0 ~ 2^32-1。如下图:

之后将各个节点散列到这个环上,可以用节点的 IP、hostname 这样的唯一性字段作为 Key 进行 hash(key),散列之后如下:

之后需要将数据定位到对应的节点上,使用同样的 hash 函数 将 Key 也映射到这个环上。

这样按照顺时针方向就可以把 k1 定位到 N1节点,k2 定位到 N3节点,k3 定位到 N2节点

容错性

这时假设 N1 宕机了:

依然根据顺时针方向,k2 和 k3 保持不变,只有 k1 被重新映射到了 N3。这样就很好的保证了容错性,当一个节点宕机时只会影响到少少部分的数据。

拓展性

当新增一个节点时:

在 N2 和 N3 之间新增了一个节点 N4 ,这时会发现受印象的数据只有 k3,其余数据也是保持不变,所以这样也很好的保证了拓展性。

虚拟节点

到目前为止该算法依然也有点问题:

当节点较少时会出现数据分布不均匀的情况:

这样会导致大部分数据都在 N1 节点,只有少量的数据在 N2 节点。

为了解决这个问题,一致哈希算法引入了虚拟节点。将每一个节点都进行多次 hash,生成多个节点放置在环上称为虚拟节点:

计算时可以在 IP 后加上编号来生成哈希值。

这样只需要在原有的基础上多一步由虚拟节点映射到实际节点的步骤即可让少量节点也能满足均匀性。

号外

最近在总结一些 Java 相关的知识点,感兴趣的朋友可以一起维护。

地址: https://github.com/crossoverJie/Java-Interview

一致 Hash 算法分析的更多相关文章

  1. 一致性 Hash 算法分析

    当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题: 如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少. Hash 取模 随机放置就不说了,会带来很多问 ...

  2. Cuckoo hash算法分析

    一 基本思想: cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间 基本思想是使用2个hash函数来处理 ...

  3. 【转】【java源码分析】Map中的hash算法分析

    全网把Map中的hash()分析的最透彻的文章,别无二家. 2018年05月09日 09:08:08 阅读数:957 你知道HashMap中hash方法的具体实现吗?你知道HashTable.Conc ...

  4. Cuckoo hash算法分析——其根本思想和bloom filter一致 增加hash函数来解决碰撞 节省了空间但代价是查找次数增加

    基本思想: cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间 基本思想是使用2个hash函数来处理碰撞 ...

  5. 一致性 Hash 算法的实际应用

    前言 记得一年前分享过一篇<一致性 Hash 算法分析>,当时只是分析了这个算法的实现原理.解决了什么问题等. 但没有实际实现一个这样的算法,毕竟要加深印象还得自己撸一遍,于是本次就当前的 ...

  6. .Net 中HashTable,HashMap 和 Dictionary<key,value> 和List<T>和DataTable的比较

    参考资料 http://www.cnblogs.com/MichaelYin/archive/2011/02/14/1954724.html http://zhidao.baidu.com/link? ...

  7. C#中Dictionary,Hashtable,List的比较及分析

    一. Dictionary与Hashtable Dictionary与Hashtable都是.Net Framework中的字典类,能够根据键快速查找值 二者的特性大体上是相同的,有时可以把Dicti ...

  8. 【Java】留下没有基础眼泪的面试题

    前言 只有光头才能变强 本文力求简单讲清每个知识点,希望大家看完能有所收获 一.如何减少线程上下文切换 使用多线程时,不是多线程能提升程序的执行速度,使用多线程是为了更好地利用CPU资源! 程序在执行 ...

  9. hashTabel List 和 dic

    hashTabel  List  和 dic 原:https://www.cnblogs.com/jilodream/p/4219840.html .Net 中HashTable,HashMap 和 ...

随机推荐

  1. mac抓包工具anyproxy

    本文以 mac为代理,ios手机为客户端举例. 文档地址:http://anyproxy.io/ 1.环境配置: 安装  node  :参考   https://www.jianshu.com/p/3 ...

  2. 业务线接入前端异常监控sentry

    1.前端异常处理的框架对比   是否开源 收费 语言 监控范围 sentry 是 自己搭建服务器(免费)价格 英文 Angular.AngularJs.Backbone.Ember.JavaScrip ...

  3. 2018年多校第三场第一题 A. Ascending Rating hdu6319

    比赛地址:http://acm.hdu.edu.cn/contests/contest_show.php?cid=804 题目编号:第一题 A. Ascending Rating  hdu6319 题 ...

  4. ZOJ4043 : Virtual Singers

    将所有$A$和$B$混在一起排序,那么每个$B$要匹配一个$A$,从左往右依次考虑每个数: 如果是一个$B$: 如果左边没有多余的$A$,那么将其放入堆$q_C$中,表示这个$B$还未匹配. 否则选择 ...

  5. OI暑假集训游记

    莞中OI集训游记 Written BY Jum Leon. I        又是一载夏,本蒟蒻以特长生考入莞中,怀着忐忑的心情到了8月,是集训之际.怀着对算法学习的向往心情被大佬暴虐的一丝恐惧来到了 ...

  6. 如何使用$.each()与$().each()以及他们的区别

    1.首先,说下$.each(Arry/Object,function(index,val){ //index表示下标,val表示下标对应的值 }) 下面是使用$.each()的几种类型,其中arr2与 ...

  7. vue项目开发基本目录结构

    § 目录结构 . ├── build/ # Webpack 配置目录 ├── dist/ # build 生成的生产环境下的项目 ├── src/ # 源码目录(开发都在这里进行) │ ├── ass ...

  8. Where is the Marble? (寻找大理石上的数字)

    (先上题目) (题目描述)Raju and Meena love to play with Marbles. They have got a lot of marbles with numbers w ...

  9. JS Fetch

    使用Fetch 1.进行 fetch 请求 一个基本的 fetch请求设置起来很简单.看看下面的代码: fetch('http://example.com/movies.json') .then(fu ...

  10. Devexpress Ribbon 动态生成菜单

    /// <summary> /// 动态加载菜单 /// </summary> private void GetMenuBind() { //根据登录用户角色菜单动态创建 // ...