您的位置:首页 > 其它

了解一致性hash算法

2017-02-08 21:14 204 查看
看到一遍介绍Consistent Hashing 的文章,通俗易懂,特记录

 转自 http://blog.csdn.net/ccyours/article/details/51495878
事情由来

公司要做一个基于discu
4000
z的论坛,需要支持同时在线千万级别,而discuz用于判断用户是否登录依据”session“常常是保存在数据库里面的,并且基于一张表保存,那么,当同时有大量用户挤入,会不会造成数据库无法承受而导致运行缓慢?答案是肯定的。那么,基于这种原因,我打算用分布式Redis来解决这个问题。按着不同的维度,这里可以是地区,活跃度等把用户登录信息分布存储在不同的redis中。

常用的负载均衡算法

在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least- Connection)、响应速度算法(Response Time)、加权法(Weighted )等。其中哈希算法是最为常用的算法。那么,如果换做是你,当一个数据需要存入redis中,你会怎么选择存储的redis?这里我们假设有四台redis1,redis2,redis3,redis4。

1.hashResult = hash();//这里hash算法是你自定义算法,总之会得出一个unsigned int型的数据

2.hashResult  % 4 =  1;//假如余数为1,

好,当前这个要存储的数据存放在第一台redis中。以此类推,把所有的数据分别进行hash和取模,存放到余数的redis中。这样的方法会有一个致命的问题,当四台redis的其中一台redis1死机(down了),那么存放在这台redis1中的数据就丢失了,相当于有 (N-1)/ N,即  3/4 台的数据需要重新计算存放位置。这对系统是致命的打击。那么怎么能合理存放数据,并且能够任意的增加或删除redis机器呢?答案是
 一致性hash.

一致性hash介绍

关于一致性hash的介绍,网上有很多,大家自行google即可。这里我简单的盗图说明一下,哈哈哈。省事!

由于hash算法结果一般为unsigned

int型,因此对于hash函数的结果应该均匀分布在[0,232-1]间,如果我们把一个圆环用232  个点来进行均匀切割

,首先按照hash(key)函数算出服务器(节点)的哈希值,

并将其分布到0~232的圆上。用同样的hash(key)函数求出需要存储数据的键的哈希值,并映

射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器(节点)上。如下

新增一个redis节点的时候,只有在圆环上新增节点逆时针方向的第一个redis节点的数据会受到影响。删除一个redis节点的时候,只有在圆环上原来删除

节点顺时针方向的第一个节点的数据会受到影响,因此通过Consistent

Hashing很好地解决了负载均衡中由于新增节点、删除节点引起的hash值颠簸问题

。如下图:



学习困惑

1.为什么hash算法结果会分布在1-2^32 -1的范围呢?

2.那一般企业redis大多不超过十台,因此每台redis之间的环的角度可能出现不平衡性(例如redis1占用了一半圆,其余的redis来分剩余一半圆环),所以当数据量较大的时候,运用一致性hash还是会出现数据分布不均匀的情况,从而破坏了hasn算法的ping。怎么办?

这里引入虚拟节点的概念:虚拟节点可以认为是实际节点的复制品(replicas),其实就是redis1又生了很多个孩子redis1-1,redis1-2,这样redis1家族通过hash算出来的位置会均匀的分布在圆环中各个位置。在进行负载均衡时候,落到虚拟节点的哈希值实际就落到了实际的节点上。由于所有的实际节点是按照相同的比例复制成虚拟节点的,因此解决了节点数较少的情况下哈希值在圆环上均匀分布的问题。

3.我们运用一致性hash的算法的最终目的是干什么?

简单的说,是用来取出一个节点。这个节点用来存放或者读取你想要存放或者读取的数据。

参考 http://blog.csdn.net/cywosp/article/details/23397179/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: