Python数据结构与算法-哈希map的实现及原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python数据结构与算法-哈希map的实现及原理相关的知识,希望对你有一定的参考价值。
参考技术A1-collections.MutableMapping
1.1 概念:这是什么?
大家可能想知道这一串英文是什么意思?其实只需要了解在collections库当中有一个非常重要的抽象基类MutableMappin
g,专门用于实现map的一个非常有价值的工具。后边我们会用到它。
2-我们的map基类
2.1 实现这个类
这个基类其实也就是确定了键值对的属性,并且存储了基本的比较方法。它的对象就是一个键值对咯。这个很好理解。有点类似object的感觉。
3-通过map基类实现的无序映射
给大家看一个上边的例子,这个例子来源于网络,自己改了改,能用,更加详细而已,凑合看.
4-Python哈希表的实现的基类
4.1 咱有话直说:上才(代)艺(码)
如果还不知道哈希表概念的同xio,请参考 python进阶之数据结构与算法–中级-哈希表(小白piao分享) 。废话不多说,咱们撸代码:
OK了,基本的哈希表就实现了,其实仔细想想很容易,但是自己要能实现还是要理解哈希表的本质哦,外加一定量的练习才可以熟练掌握,练习的目的就是为了熟练而已。
5-分离链表实现的具体哈希map类
说明:这玩意只是一种降低冲突的手段,上一节提过,降低冲突最好的地方是发生在元组进入桶的时候,所以想必大家猜到了,接下来的分离链表也就是为了self._bucket_xxxxxxx系列方法做准备。这里之所以在上边使用@abstractmethod就是为了继承实现,目的可以实现多种将冲突的哈希表。分离链表的概念上一节也有的。
“见码入面”(借鉴:见字如面这个电视节目,有兴趣可以看看,还不错的):
6-用线性探测处理冲突的哈希map类
这种方式的好处不需要再去借助其他额外的赋值结构来表示桶。结构更加简单。不会再像上一种方法还要让桶是一个UnsortedTableMap的对象。
代码如下:
浅析一致性哈希算法的原理及实现
1.分布式缓存问题
以上是单节点环境下,但随着流量的增大,可能就演变为了如下情形:
❓这个负载均衡算法该如何设计最为合理呢?
首先能想到的最简单的方法可能就是随机或者轮询,这样会产生两个问题:一是数据冗余;二是数据可能已经被缓存,但请求却命中了不存在该数据的节点上。
如何解决这个问题?只需要保证相同的key被发送给相同节点上即可。再一想这不就是hash算法嘛【index = hash(key) % n】(n为节点的数量)
public class SimpleHash
public int loadBalance(String key)
return hash(key) % 3;
private int hash(String key)
int hash = Math.abs(key.hashCode());
.....
.....
return hash;
这种算法它的容错性和扩展性不是很好;一旦某个节点宕机或者加入新的节点时,导致n发生了变化,需要重新hash计算,这样可能导致大量缓存不命中,一瞬间给磁盘数据库造成了很大的压力。
容错性是指当某个节点宕机时,整个系统是否可以继续高效运行;扩展性是指加入新节点时,整个系统是否可以高效运行。
所以这种简单的哈希算法并不适用于实际场景,而本文所讲的一致性哈希算法解决了大量哈希重定位的问题。
2.一致性哈希算法
一致性哈希引入了一个虚拟的圆环,这个圆环有2^32个节点组成(0~ 2^32);
📚它的原理如下:
(1)对每个缓存服务器的IP作为key进行哈希计算,得到的结果一定分布在环上。
(2)对每个数据作为key进行哈希计算,得到的结果也一定分布在环上
按照顺时针,第一台遇到的节点就是该数据定位到的服务器。
❓当节点宕机或者添加新的节点时,它会出现什么样的结果呢?
public class ConsistentHash
private static final String[] NODES = "123.23.34.1", "123.52.2.1", "43.122.54.1";
//模拟环形哈希表
private static final SortedMap<Integer, String> CIRCLE_Map = new TreeMap<>();
static
for (String node : NODES)
int index = hash(node);
System.out.println(node + "节点的哈希值为:" + index);
CIRCLE_Map.put(index, node);
public static String loadBalance(String key)
int index2 = hash(key);
//返回一个大于或等于index2的map
SortedMap<Integer, String> tailMap = CIRCLE_Map.tailMap(index2);
//如果tailMap为空,则直接返回哈希表的第一个数据
if (tailMap.isEmpty())
return CIRCLE_Map.get(CIRCLE_Map.firstKey());
else
//第一个Key就是顺时针过去离node最近的那个结点
return CIRCLE_Map.get(tailMap.firstKey());
private static int hash(String key)
........
........
public static void main(String[] args)
System.out.println("zsh被路由到的节点为:" + loadBalance("zsh"));
此时可以看到只有一小部分数据进行了重定位,所以它具有很好的容错性和扩展性,❓那么它就没一点问题吗?答案肯定不是的,在某种情况下,会出现节点倾斜的问题。
当节点2宕机之后,数据1和数据2都重定位到了节点3上,节点分布式不均匀会导致数据倾斜的问题。
3.引入虚拟节点
解决数据倾斜问题,可以通过增加大量节点使其分布均匀;但是实际上不可行,太浪费钱。所以引入虚拟节点,并将虚拟机节点定位到某个物理节点上即可。
如下图引入v1~v6虚拟节点,并建立与物理节点的映射关系;如定位到v1和v2的数据均定位到节点1上。
带虚拟节点的哈希算法实现
public cl
以上是关于Python数据结构与算法-哈希map的实现及原理的主要内容,如果未能解决你的问题,请参考以下文章