目标:将服务器处理的每个网址映射到0,1,2或3,尽可能均匀地分布。
虽然ruby的String #hash方法的documentation表示它将“根据字符串的长度和内容返回一个哈希值”,但这显然不是全部。给定字符串的散列在解释器的调用之间不一致:
$ irb
ruby-1.9.2-p180 :001 > "foo".hash
=> 360517580588231756
ruby-1.9.2-p180 :002 > ^D
$ irb
ruby-1.9.2-p180 :001 > "foo".hash
=> -2716152678666510148
这意味着特定字符串的哈希值可能会因服务器而异。 Rails在内部使用String#hash
将URL路径映射到四个资产主机之一(如果应用程序的asset_host为so configured),但由于跨机器,此功能的效率低得多不一致;不同的服务器可能会将相同的URL映射到不同的资产主机,从而降低了缓存的效率,使天空蒙上阴影,过早地冷却了茶杯,破坏了其他优秀程序员的声誉。
你能否建议一个备用哈希函数,可以有效,快速地在典型应用程序的URL空间中分配哈希值,最好是生成Fixnum的哈希函数,最后,我想将它映射到四个资产主机之一?
答案 0 :(得分:30)
ruby的摘要模块中有很多这样的功能:http://ruby-doc.org/stdlib/libdoc/digest/rdoc/index.html
简单的例子:
require 'digest/sha1'
Digest::SHA1.hexdigest("some string")
答案 1 :(得分:2)
有一个很小的库xxHash:
XXhash.xxh32('qwe') #=> 2396643526
XXhash.xxh64('qwe') #=> 9343136760830690622
也许它会有更多的碰撞,但它比SHA1快10倍:
Benchmark.bm do |x|
n = 100_000
str = 'qweqweqwe'
x.report('xxhash32') { n.times { XXhash.xxh32(str) } }
x.report('xxhash64') { n.times { XXhash.xxh64(str) } }
x.report('hexadigest') { n.times { Digest::SHA1.hexdigest(str) } }
end;1
# user system total real
# xxhash32 0.020000 0.000000 0.020000 ( 0.021948)
# xxhash64 0.040000 0.000000 0.040000 ( 0.036340)
# hexadigest 0.240000 0.030000 0.270000 ( 0.276443)
答案 2 :(得分:1)
您可以尝试to_i(36)。
"Hash me please :(".to_i(36)
=> 807137
答案 3 :(得分:1)
最简单(且始终如一)的方法可能是这种方式(而且速度很快):
"https://www.example.com/abc/def/123?hij=345".sum % 4
那将总是产生一个0到3的整数,速度非常快,并且应该分布得很好(尽管我实际上没有在分布上运行测试)。