架构师 1 期 - 技术选型 (一) 作业
发布于: 2020 年 10 月 24 日
我使用 ruby 实现一致性 hash
首先实现一个虚拟节点的类
module ConsistentHashing
class VirtualPoint
attr_reader :node, :index
def initialize(node, index)
@node = node
@index = index.to_i
end
def index=(index)
@index = index.to_i
end
end
end
复制代码
一致性 hash 的主要逻辑
module ConsistentHashing
class Ring
def initialize(nodes = [], replicas = 3)
@replicas = replicas
@ring = AVLTree.new
nodes.each { |node| add(node) }
end
def add(node)
@replicas.times do |i|
key = hash_key(node, i)
@ring[key] = VirtualPoint.new(node, key)
end
end
def delete(node)
@replicas.times do |i|
key = hash_key(node, i)
@ring.delete key
end
end
def point_for(key)
return nil if @ring.empty?
key = hash_key(key)
_, value = @ring.next_gte_pair(key)
_, value = @ring.minimum_pair unless value
value
end
def node_for(key)
point_for(key).node
end
protected
def hash_key(key, index = nil)
key = "#{key}:#{index}" if index
Digest::MD5.hexdigest(key.to_s)[0..16].hex
end
end
end
复制代码
数组搜索大于等于目标值的最小值节点比较慢,改为 AVLTree 的 #next_gte_pair 方法
require 'consistent_hashing'
require 'descriptive_statistics'
servers = []
(0..9).each do |i|
servers << "192.168.1.10#{i}"
end
(1..20).each do |time|
h_count = {}
ring = ConsistentHashing::Ring.new(servers, time)
(1..1000000).each do |i|
n = "n#{i}"
server = ring.node_for(n)
if h_count[server].nil?
h_count[server] = 1
else
h_count[server] += 1
end
end
puts ring.points.size
puts h_count.values.standard_deviation
end
复制代码
100 万数据测试程序 10 个节点标准差 74545
100 万数据测试程序 100 个节点标准差 26218
100 万数据测试程序 150 个节点标准差 20409
之后一直是在 20000 上下
说明 150 个节点是比较合理的
划线
评论
复制
发布于: 2020 年 10 月 24 日阅读数: 36
ltl3884
关注
还未添加个人签名 2017.12.08 加入
还未添加个人简介
评论