分布式系统设计理论之一致性哈希

简介: 分布式系统设计理论之一致性哈希

分布式系统设计理论之一致性哈希

主要参考和围绕这篇论文讲解:Consistent Hashing

1 问题引入

什么是一致性哈希?为什么要用一致性哈希?

2 一致性哈希算法出现之前的分布式系统设计

例如系统需要构建分布式缓存,多个节点分别部署而形成的一个分布式集群,当有请求到来时进行负载均衡,具体的负载均衡方式就是将节点的ID(唯一标识)进行哈希值的取余运算,得到结果的机器就是进行请求处理的机器。

上述方式存在的问题

当一个节点进行更换(增加或删除节点)时,原有的节点消失或增加新的节点,会导致多个请求同时指向一个节点进而造成节点的宕机等问题。

总之一句话就是,当服务器个数发生改变时,缓存可能会失效。

图解:

正常情况下:

删除一个服务器之后:

3 什么是一致性哈希,它是如何解决上述问题的?

3.1 一致性哈希的核心思想

⼀致性哈希算法的基本思想是使⽤相同的哈希函数服务器节点对象和请求的缓存进⾏哈希,即⼀致地将对象映射到相同的缓存机器。

3.2 引入哈希环

整数int在Java中的取值范围是2的-31次方到2的31次方-1之间,那么就可以让请求的缓存和服务器节点同时进行相同的哈希算法后得到一个int值,进而形成一个哈希环,请求和服务器节点保持“顺时针就近”原则进行对应的请求:

A,B,C代表三个服务器节点,1,2,3,4代表着不同的缓存请求,按照“顺时针就近”原则,1,4会请求服务器A节点,2请求服务器B节点,3请求服务器C节点。

3.3 存在问题
(1)增删节点带来的问题

新增服务器节点D,按照之前的原则4就会向服务器D节点发起请求,在4和D之间的一部分缓存将会失效,这是问题之一。

(2)哈希倾斜

所谓哈希倾斜就是表示如上图,服务器A,B相距较近,假如没有服务器D节点,那么B到A这一段的请求都会落在A节点上,即大部分请求都指向A节点,而极少部分请求放在了B节点,这个问题就是“哈希倾斜”。

3.4 增加虚拟节点解决问题

解决上边两个问题的最佳方案就是增加虚拟节点,就是在哈希环中增加无数个虚拟节点,请求指向虚拟节点,虚拟节点指向真实节点,这样就会增加请求平均的概率,如图:

而且论文中还指出,虚拟节点的数量越大,请求产生的偏差越小:

4 Java代码实现一致性哈希

/**
 * @desc: Java实现一致性哈希
 * @author: YanMingXin
 * @create: 2021/10/16-16:46
 **/
public class ConsistentHash<T> {
    /**
     * 哈希函数类
     */
    private final HashFunction hashFunction;
    /**
     * 虚拟节点个数(不同节点一共的,会自动平均)
     */
    private final int numberOfReplicas;
    /**
     * 哈希环
     */
    private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();
    /**
     * 构造方法
     *
     * @param hashFunction     自定义哈希函数类(必须有hash()方法)
     * @param numberOfReplicas 副本个数
     * @param nodes            服务器节点
     */
    public ConsistentHash(HashFunction hashFunction,
                          int numberOfReplicas, Collection<T> nodes) {
        this.hashFunction = hashFunction;
        this.numberOfReplicas = numberOfReplicas;
        for (T node : nodes) {
            add(node);
        }
    }
    public ConsistentHash(int numberOfReplicas, Collection<T> nodes) {
        this.hashFunction = new HashFunction();
        this.numberOfReplicas = numberOfReplicas;
        for (T node : nodes) {
            add(node);
        }
    }
    /**
     * 向哈希环增加节点的副本
     *
     * @param node
     */
    public void add(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.put(hashFunction.hash(node.toString() + i), node);
        }
    }
    /**
     * 删除节点
     *
     * @param node
     */
    public void remove(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.remove(hashFunction.hash(node.toString() + i));
        }
    }
    /**
     * 根据请求得到他将要访问的节点
     *
     * @param key
     * @return
     */
    public T get(Object key) {
        if (circle.isEmpty()) {
            return null;
        }
        //将请求hash转换
        int hash = hashFunction.hash(key);
        //将请求放入哈希环
        if (!circle.containsKey(hash)) {
            //返回该映射中键值大于或等于hash的部分的视图。 
            SortedMap<Integer, T> tailMap = circle.tailMap(hash);
            //判断tailMap是否为空,是则返回哈希环第一个节点的值,反之则返回最近的节点
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        return circle.get(hash);
    }
    /**
     * 哈希函数类
     */
    class HashFunction {
        /**
         * 具体的哈希函数
         *
         * @param key
         * @return
         */
        public int hash(Object key) {
            return key.hashCode() / Integer.MAX_VALUE;
        }
    }
}

部分图片和内容来自:http://tom-e-white.com/2007/11/consistent-hashing.html

相关文章
|
4月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
1月前
|
消息中间件 缓存 算法
分布式系列第一弹:分布式一致性!
分布式系列第一弹:分布式一致性!
|
1月前
|
算法 Java 关系型数据库
漫谈分布式数据复制和一致性!
漫谈分布式数据复制和一致性!
|
3月前
|
存储 算法 NoSQL
(七)漫谈分布式之一致性算法下篇:一文从根上儿理解大名鼎鼎的Raft共识算法!
Raft通过一致性检查,能在一定程度上保证集群的一致性,但无法保证所有情况下的一致性,毕竟分布式系统各种故障层出不穷,如何在有可能发生各类故障的分布式系统保证集群一致性,这才是Raft等一致性算法要真正解决的问题。
112 11
|
3月前
|
存储 算法 索引
(六)漫谈分布式之一致性算法上篇:用二十六张图一探Raft共识算法奥妙之处!
现如今,大多数分布式存储系统都投向了Raft算法的怀抱,而本文就来聊聊大名鼎鼎的Raft算法/协议!
114 8
|
3月前
|
存储 算法 Java
(五)漫谈分布式之一致性算法篇:谁说Paxos晦涩难懂?你瞧这不一学就会!
没在时代发展的洪流中泯然于众的道理很简单,是因为它们并不仅是空中楼阁般的高大上理论,而是有着完整落地的思想,它们已然成为构建分布式系统不可或缺的底层基石,而本文则来好好聊聊分布式与一致性思想的落地者:Paxos与Raft协议(算法)。
|
3月前
|
存储 NoSQL MongoDB
(四)成为分布式高手必经之路:理解那些工作在分布式系统底层的一致性模型
在分布式领域里,一致性成为了炙手可热的名词,缓存、数据库、消息中间件、文件系统、业务系统……,各类分布式场景中都有它的身影,因此,想要更好的理解分布式系统,必须要理解“一致性”这个概念。本文就展开聊聊 分布式系统里的一致性模型。
|
3月前
|
Oracle 关系型数据库
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决
|
3月前
|
消息中间件 存储 监控
消息队列在分布式系统中如何保证数据的一致性和顺序?
消息队列在分布式系统中如何保证数据的一致性和顺序?
|
3月前
|
消息中间件 存储 C#
分布式事务之最终一致性实现方案
分布式事务之最终一致性实现方案
78 0

热门文章

最新文章