Memcached / Dalli 无法从其他服务器获取数据

Memcached / Dalli couldn't fetch data from other servers

我们使用 memcached 作为应用程序的会话存储,我们有 2 个生产服务器,memcached 客户端是 dalli (https://github.com/mperham/dalli)。配置如下:

# Server A
config.cache_store = :dalli_store, '127.0.0.1', SERVER_B_IP, {namespace: 'Myapp', expires_in: 1.day, compress: true, failover: false}
# Server B
config.cache_store = :dalli_store, SERVER_A_IP, '127.0.0.1', {namespace: 'Myapp', expires_in: 1.day, compress: true, failover: false}

我们面临一个问题,我们的一台服务器似乎没有查找另一台服务器来获取数据。例如,如果我在服务器 B 上有 some_key 的数据,当我尝试在控制台中进行调试时:

options = {namespace: 'Myapp', expires_in: 1.day, compress: true, failover: false}
# Server A
dalli = Dalli::Client.new(['127.0.0.1', SERVER_B_IP], options)
dalli.get("some_key") # nil

# Server B
dalli = Dalli::Client.new([SERVER_A_IP, '127.0.0.1'], options)
dalli.get("some_key") # { "_csrf_token" => "..." }

我试过 failover: true 但仍然得到相同的结果。但是如果密钥 some_key 留在服务器 A 上,我可以从两台服务器获取相同的数据。

此外,在上面的示例中,如果我仅使用 SERVER_B_IP 初始化 dalli 客户端,即 dalli = Dalli::Client.new(SERVER_B_IP, options),我可以取回数据。

稍微挖掘一下代码,我发现服务器 A 上的 ring.continuum 总是指向它自己:

# Server B
ring = dalli.send :ring
hkey = ring.send :hash_for, 'some_key'                    # got same hkey
entryidx = ring.send :binary_search, ring.continuum, hkey # 300
ring.continuum[entryidx].server                           # server B
ring.continuum[302].server                                # server A

# Server A
ring = dalli.send :ring
hkey = ring.send :hash_for, 'some_key'                    # got same hkey
entryidx = ring.send :binary_search, ring.continuum, hkey # 302
ring.continuum[entryidx].server                           # server A
ring.continuum[300].server                                # server A

我是否遗漏了 memcached/dalli 配置中的某些内容?

提前致谢。

我快速浏览了一下 Daili 代码库。它使用一致性哈希将密钥分发到服务器。

https://github.com/mperham/dalli/blob/master/lib%2Fdalli%2Fring.rb#L10

entry_count_for(server, servers.size, total_weight).times do |idx|
     hash = Digest::SHA1.hexdigest("#{server.name}:#{idx}")
     value = Integer("0x#{hash[0..7]}")
     continuum << Dalli::Ring::Entry.new(value, server)
end

def entry_count_for(server, total_servers, total_weight)
     ((total_servers * POINTS_PER_SERVER * server.weight) / Float(total_weight)).floor
end

每个服务器的密钥空间取决于服务器总数、权重和服务器名称。这样密钥空间将随着总服务器或服务器名称的不同而不同。我认为这个解释符合你的问题。