对于一致性哈希技术在分布式缓存中的理解

前言:

    我们知道当随着应用中数据量越来越多,并发访问量也随之增多的时候,对于传统关系型数据库中数据的读写将会形成一定的瓶颈,因为对于磁盘的访问效率是很低的。

    为了减轻数据库在高并发环境下的压力,引入了缓存的机制,即在我们数据库之前增加一层缓存,来提高系统的响应速度。

    那对于单台机器的内存我们知道是一定的,不可能在一台机器上缓存所有的数据,所以我们需要引入分布式缓存技术。

分布式缓存技术:

    目前,主流的分布式缓存技术有 memcache,redis等。本文以memcache为例,主要讲解一致性哈希技术在分布式缓存中的应用。

    memcache是danga.com的一个项目,是一款开源的高性能的分布式内存对象缓存系统,最早是给LiveJournal提供服务的,后来逐渐被越来越多的大型网站所采用。主要用来在应用中减少对数据库的直接访问压力,提高整体应用的访问速度,减轻数据库的压力,防止由于数据库压力过高导致雪崩效应。

    memcache之所以可以提供高效的内存缓存,是因为其在内存中维护了一个巨大的hashTable,基于key-value,将数据的查询的时间复杂度控制在O(1),从而达到高效率的对数据的访问。

    那memcache既然基于内存存储缓存的数据,那就势必会存在内存不够的情况,memcache采用了一种叫做 LRU算法,(Least Recently Used)

    即将最近不常用的数据淘汰掉,以让出内存空间来存放新的需要缓存的数据。

一致性哈希:

    我们知道,分布式缓存,是因为我们采用了集群的形式搭建了缓存机器的节点。memcache本身并不是一种分布式的缓存系统,其分布式的实现其实是由访问memcache的客户端来实现的。为什么这么说呢?

    因为我们使用memcache一般简单的方式是根据缓存数据的key进行hash计算。在根据后台有几台的缓存服务器(N),通过key计算后hash值取模N得到该缓存的数据具体落在哪台缓存服务器上,从而实现分布式缓存。

    那么问题来了,当我们增加/删除 缓存服务器节点时会发生什么呢?由于缓存服务器的节点数量发生改变,取模计算后的缓存数据落点的具体节点大部分都发生了变化,比如我这个缓存数据A原来是落点在第二台缓存服务器上的,变化后就会落点在了第一台缓存服务器上,那这台服务器上由于没有我之前缓存的数据A,就会出现当有大量的请求需要获取数据A,这些请求会瞬间涌入后端的关系型数据库中。可能就会导致数据库不可用,进而导致整个应用不可用。

    这个时候本文的主角就要出场了,铛铛,铛铛......

    Consistent Hash

原理:

    首先重新定义hash函数的值域空间,原先没有采用一致性hash,hash值取模后的范围是固定在所拥有的后端缓存服务器节点数量,即N的大小。

    而一致性hash的hash函数的值域空间是一个圆环,假设其值域空间为0-3

位的无符号整型,整个空间按照顺时针方向进行组织,然后对响应的缓存服务器节点进行hash计算,将计算得到的hash值映射到hash环上,

    再根据需要缓存的数据,计算出每个数据的key的hash值,(这里使用的是和上面的hash函数一致的计算方式),将得到的值再映射到hash环上,按照顺时针方向规则,分布在node1和node2之间的key,他们的访问请求会被定位到node2上,即顺时针的下一个节点上。以此类推。

    以上就是一致性hash的实现原理,那么问题来了,加入此时新加入了节点node5,经过计算node5被hash到了node2和node4之间,那么受影响的缓存数据有哪些呢?

    通过分析我们知道,受影响的缓存key只有在node2和node5之间的数据,其他的所有缓存key均不受影响,原来存储在哪个缓存节点上的数据,现在还是存储在哪个节点上,从而最大程度的减少大量key的重新映射缓存节点的情况,这就是一致性hash带来的优势。

极端情况:

    上述的一致性hash算法,针对理想情况下是ok的,即各个缓存服务器节点在环上分布的比较均匀,比如有四台缓存服务器节点,每个缓存服务器各占环的四分之一,这是比较均匀的分布情况,那么对于分布不均匀的情况会出现什么情况呢?

    如果此时四台缓存服务器节点经过计算出的hash位置都挤在了一块,整个环空出了一大部分的空闲,那么很有可能导致很多缓存数据经过计算后的位置都落在这个空闲处,根据顺时针规则,也就是大部分的缓存数据都落在了某一个缓存服务器节点上,为了避免这种极端的情况,有没有其他好的解决方法呢?答案是有的,也就是采用虚拟节点的方式

虚拟节点:

    所谓虚拟节点机制其实就是对每一台缓存服务器节点都计算处多个hash值,每一个hash值都对应hash环上的一个节点的位置,该节点称为虚拟节点。而对于缓存数据key的映射方式不变,如果key被映射到了某一个虚拟缓存节点上,就会多出来一步再去映射到真实的缓存服务器节点,这样,如果虚拟缓存节点的数量足够多,即使只有很少的真实节点,也可以使我们缓存数据的key分布的相对均匀。

你可能感兴趣的:(对于一致性哈希技术在分布式缓存中的理解)