余数分散算法
缓存系统中应用比较多的是余数计算分散和一致性 HASH 计算分散。
原理:余数计算分散法简单来说,就是 “ 根据服务器台数的余数进行分散 ” 。
- 求得传入键的整数哈希值( int hashCode )。
- 使用计算出的 hashCode 除以服务器台数 (N) 取余数( C=hashCode % N )
- 在 N 台服务器中选择序号为 C 的服务器。
特点:余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。 那就是当添加或移除服务器时,缓存重组的代价相当巨大。 添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器, 从而影响缓存的命中率。
比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,用这个方法计算 object 的 hash 值,然后均匀的映射到到 N 个 cache ;hash(object)%N
一切都运行正常,再考虑如下的两种情况;
1.一个 cache 服务器 m down 掉了(在实际应用中必须要考虑这种情况),这样所有映射到 cache m 的对象都会失效,怎么办,需要把 cache m 从 cache 中移除,这时候 cache 是 N-1 台,映射公式变成了 hash(object)%(N-1) ;
2.由于访问加重,需要添加 cache ,这时候 cache 是 N+1 台,映射公式变成了 hash(object)%(N+1) ;
这意味着突然之间几乎所有的 cache 都失效了。对于服务器而言,这是一场灾难,洪水般的访问都会直接冲向后台服务器;
再来考虑第三个问题,由于硬件能力越来越强,你可能想让后面添加的节点多做点活,显然这个 算法也做不到。
Hash 算法的一个衡量指标是单调性( Monotonicity ),定义如下:
单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
容易看到,这个算法 hash(object)%N 难以满足单调性要求。