一致 Hash 算法分析
当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题:
如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少。
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 相关的知识点,感兴趣的朋友可以一起维护。
一致 Hash 算法分析的更多相关文章
- 一致性 Hash 算法分析
当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题: 如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少. Hash 取模 随机放置就不说了,会带来很多问 ...
- Cuckoo hash算法分析
一 基本思想: cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间 基本思想是使用2个hash函数来处理 ...
- 【转】【java源码分析】Map中的hash算法分析
全网把Map中的hash()分析的最透彻的文章,别无二家. 2018年05月09日 09:08:08 阅读数:957 你知道HashMap中hash方法的具体实现吗?你知道HashTable.Conc ...
- Cuckoo hash算法分析——其根本思想和bloom filter一致 增加hash函数来解决碰撞 节省了空间但代价是查找次数增加
基本思想: cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间 基本思想是使用2个hash函数来处理碰撞 ...
- 一致性 Hash 算法的实际应用
前言 记得一年前分享过一篇<一致性 Hash 算法分析>,当时只是分析了这个算法的实现原理.解决了什么问题等. 但没有实际实现一个这样的算法,毕竟要加深印象还得自己撸一遍,于是本次就当前的 ...
- .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? ...
- C#中Dictionary,Hashtable,List的比较及分析
一. Dictionary与Hashtable Dictionary与Hashtable都是.Net Framework中的字典类,能够根据键快速查找值 二者的特性大体上是相同的,有时可以把Dicti ...
- 【Java】留下没有基础眼泪的面试题
前言 只有光头才能变强 本文力求简单讲清每个知识点,希望大家看完能有所收获 一.如何减少线程上下文切换 使用多线程时,不是多线程能提升程序的执行速度,使用多线程是为了更好地利用CPU资源! 程序在执行 ...
- hashTabel List 和 dic
hashTabel List 和 dic 原:https://www.cnblogs.com/jilodream/p/4219840.html .Net 中HashTable,HashMap 和 ...
随机推荐
- CentOS6.x 下 /etc/security/limits.conf 被改错的故障经历
Intro 我司本小厂,每个员工都是身兼数职,所以开发人员直接登录线上服务器改东西是常态.有些开发人员,自持水平较高(的确水平也是较高,但缺乏对系统的敬畏),所以总是越俎代庖,改一些本身应该是线上运维 ...
- python+adb实现自动化获取手机信息
首先我们先看一下使用adb查看Android手机信息的指令 #获取手机名称NAME = 'adb shell getprop ro.product.model'#获取手机版本VERSION = 'ad ...
- 线程池ThreadPoolTaskExecutor配置说明
一般实际开发中经常用到多线程,所以需要使用线程池了, ThreadPoolTaskExecutor通常通过XML方式配置,或者通过Executors的工厂方法进行配置. XML方式配置代码如下:交给 ...
- python 字典、列表、字符串 之间的转换
1.列表与字符串转换 1)列表转字符串: 将列表中的内容拼接成一个字符串 将列表中的值转成字符串 2)字符串转列表: 用eval转换 将字符串每个字符转成列表中的值 将字符串按分割成列表 2.列表与字 ...
- hdu 3478 Catch--二分图判断
我觉得,给了初始点的话用bfs方便点,没有则dfs ||可能超片面 https://vjudge.net/contest/281085?tdsourcetag=s_pcqq_aiomsg#proble ...
- SVM:根据大量图片来精确实现人脸识别—Jason niu
from __future__ import print_function from time import time import logging import matplotlib.pyplot ...
- 【redis】在dotnet core下的redis的使用
1.Install-Package Microsoft.Extensions.Caching.Redis -Version 2.2.0 2.注入 services.AddDistributedRedi ...
- 2019-3-26WinForm窗体间如何传值的几种方法
窗体间传递数据,无论是父窗体操作子窗体,还是子窗体操作符窗体,有以下几种方式: 公共静态变量: 使用共有属性: 使用委托与事件: 通过构造函数把主窗体传递到从窗体中: 一.通过静态变量 特点:传值是双 ...
- 算法第四版中 while (!StdIn.isEmpty()) 循环无法跳出问题
在IDEA中使用Ctrl+D就可以退出console输入
- 使用PIA查找组件的PeopleSoft导航
导航到企业组件>查找对象导航. 使用组件名称 使用页面名称 使用辅助页面名称 使用内容参考名称 只需输入对象名称,然后单击“搜索”即可.在这个例子中.我们知道组件名称即'PRCSDEFN',我们 ...