小明是邮局的人事部,主要管给邮件分类的人员。最近人员调动比较大,导致遇见了以下难题。
目标:确定每个员工要处理的邮件省份的分配策略。
条件:1)一个员工如果长时间处理相同省份的邮件,分类效率会提高。
2)随时有员工离职或者加入,要求实时分配任务。
分析:问题一看就是明白是散列直接的对应问题(省份散列->员工散列),很明显的应该用哈希算法。如果没有条件一,很明显的就用普通的hash算法(hash(object)%N)就行,但考虑条件一,就必须在添加或删除员工时,不影响(或较小影响)其他在职员工的分配。一致性哈希就能解决这个问题。
一致性hash:
下面介绍一致性hash算法,图都是从网上找的,不属于原创。
简单的说一致性hash就是把所有散列都通过一种规则(算法)都分布到一个圆环上,如下图
*蓝点为员工,红点为省份
这样分配策略就出现了,key1分配给A,key4分配给B,key2,3分配给C
如果来了一个新员工D,新的分布如下图
分配策略就变成了,key1分配给A,key4分配给B,key2分配给D,key3分配给C。可以看到大部分员工分配的省份都没有变。
如果走了一个员工,新的分布如下图
分配策略就变成了,key1分配给A,key4,2,3分配给C。可以看到大部分员工分配的省份都没有变。
这样问题就解决了。
不过又过了几天,小明又遇到了难题,有个员工B病了,所有的事都交给员工C,C由于工作太多,连续加班好几天也病了,这样没过几天大家都病了,分邮件的工作完全就没人做了!!!
这就是所说的雪崩效应,就因为有个员工小生了一下病就会导致系统完全没法工作。说明上面的分配策略还不完善。
分析:由于单点(员工)暂时离开,导致某点(员工)工作量加倍,超出单点最大处理能力。
解决策略:单点(员工)暂时离开后的任务应该尽可能分配均匀分配到现在可工作的点(员工)。
虚拟节点:
虚拟节点”(virtual node)是实际节点在hash空间的复制品(replica),一实际个节点对应了若干个“虚拟节点”,这个对应个数也成为“复制个数”,“虚拟节点”在hash空间中以hash值排列。
通过把员工虚拟出多个员工,比如4个员工ABCD,每个虚拟出2个,也就是A1A2B1B2C1C2D1D2,hash后可能分布如下A1B1A2C1B2C2D1D2,如果A离开,那B1和C1会得到任务,相当于B,C每人得到了A一半任务,起到均匀的目的。一般可以虚拟几十到上百个,可以根据实际情况而定。
到此小明的问题也就解决了。