******************转载请注明出处!**********
最后更新:2011年8月22日22:47:38
Part1中,已经构建好了一致性哈希ring的原型。
但存在一个问题。100个结点对应着1000个虚结点。结点变动时,虚结点和结点的对应关系会发生变化。当100个结点扩张到1001个时,会发生什么情况?
新增的结点数目会挤兑掉原先的结点数目!原因就在于1000个虚结点是固定的,不变化的。如果再扩容1000个虚结点->更改虚结点和实结点之间的对应关系->调整数据,这似乎又回到ring2_0.py的老套路。
这里做一些改动以更接近真实情况。
首先是vnode,以后改称为partition。因为partition数量很少会变动,所以需要充分估计到系统预期的规模。假如不会超过6000个结点,那么虚结点可以设置为实结点的100倍。这样,当虚结点需要调整的时候,最多只会影响到1%的数据。
在计算机中,数字取2的幂阶会有一些好处。比如除法只需要移相应的位就可以了。所以ring3_0.py中,结点数为65536(2^16),partition数为8388608(2^23)个。
ring3_0.py
from array import array
from hashlib import md5
from struct import unpack_from
from time import time
PARTITION_POWER = 23
PARTITION_SHIFT = 32 - PARTITION_POWER
NODE_COUNT = 65536
DATA_ID_COUNT = 100000000
begin = time()
part2node = array('H')
for part in xrange(2 ** PARTITION_POWER):
part2node.append(part % NODE_COUNT)
node_counts = [0] * NODE_COUNT
for data_id in xrange(DATA_ID_COUNT):
data_id = str(data_id)
part = unpack_from('>I',
md5(str(data_id)).digest())[0] >> PARTITION_SHIFT
node_id = part2node[part]
node_counts[node_id] += 1
desired_count = DATA_ID_COUNT / NODE_COUNT
print '%d: Desier data ids per node' % desired_count
max_count = max(node_counts)
over = 100.0 * (max_count - desired_count) / desired_count
print '%d Most data ids on one node, %.02f%% over' % (max_count, over)
min_count = min(node_counts)
under = 100.0 * (desired_count - min_count) / desired_count
print '%d Least data ids on one node, %.02f%% under' % (min_count, under)
print '%d seconds pass ...' % (time() - begin)
结果
1525: Desier data ids per node
1683 Most data ids on one node, 10.36% over
1360 Least data ids on one node, 10.82% under
234 seconds pass ...
说明:
代码比较简单,part2node是no