Consistent String#hash仅基于字符串的内容

目标:将服务器处理的每个URL映射到0,1,2或3,尽可能均匀地分布。

虽然ruby的String#hash方法的文档说它将“根据字符串的长度和内容返回一个哈希值”,但这显然不是全部。 给定字符串的散列在解释器的调用之间不一致:

$ 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内部使用String#hash将URL路径映射到四个资产主机之一(如果应用程序的asset_host 配置如此 ),但由于跨机器不一致,此function的效率要低得多; 不同的服务器可能会将相同的URL映射到不同的资产主机,从而降低了缓存,阴云密布,过早冷却茶杯的效率,破坏了其他优秀程序员的声誉。

你能否建议一个备用哈希函数,它可以有效,快速地在典型应用程序的URL空间中分配哈希值,最好是生成Fixnum的哈希值,最后,我想将它映射到四个资产主机之一?

在ruby的摘要模块中有很多这样的function: http : //ruby-doc.org/stdlib/libdoc/digest/rdoc/index.html

简单的例子:

 require 'digest/sha1' Digest::SHA1.hexdigest("some string") 

有一个很小的库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) 

你可以尝试to_i(36) 。

 "Hash me please :(".to_i(36) => 807137 

最简单(和一致)的方式可能就是这个(而且速度很快):

 "https://www.example.com/abc/def/123?hij=345".sum % 4 

这将总是产生一个整数0 – 3,非常快,并且应该相当好地分布(虽然我实际上没有在分布上运行测试)。