在提供分布式集群服务的系统中,在索引对象的存储节点的方法中比较常用的方法即简单的hash集群,即使用存储对象的hash值来索引指定的存储节点。
但其中存在几个问题:
- 若其中一个节点crash了,再使用固定hash模数时,大部分的存储对象的存储节点都会发生变化,若作存储对象迁移的话数据量非常大。
- 物理节点个数少时,由于hash函数的计算特性会导致索引分布在某些情况下极度不均匀。
一致性hash能够比较好的解决此类问题,一致性哈希算法(Consistent Hashing)最早在David Karger,Eric Lehman等人的论文《Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web》中被提出,是当前较主流的分布式哈希表协议之一。
网上有非常多的对该算法的详解,此处不再多说,只贴出下图大概表示下一致性hash的大概结构:
将存储节点通过hash方式分布到0—2^32-1的连续环上,存储对象通过hash方式落于环中,取顺时针的第一个存储节点为存储服务节点。为解决均匀性问题,使用一个节点映射多个虚拟节点来使节点均匀在环上均匀分布。
存储对象与存储虚拟节点及真实节点的映射关系:
在memcache的client端的libmemcached中已经实现了该算法。以下是自己所作的Golang实现。完整代码可见:https://github.com/royhunter/ConsistentHash
1 | package main |
C语言实现版本:http://www.codeproject.com/Articles/56138/Consistent-hashing
Reference: