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

Rob*_*vis 28 ruby hash ruby-on-rails-3

目标:将服务器处理的每个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 
Run Code Online (Sandbox Code Playgroud)

这意味着特定字符串的哈希值可能在服务器之间不同.Rails在String#hash内部使用URL路径映射到四个资产主机之一(如果应用程序的asset_host 配置如此),但由于跨机器的不一致性,此功能的效率低得多; 不同的服务器可能会将相同的URL映射到不同的资产主机,从而降低了缓存的效率,使天空变得模糊,过早地冷却了茶杯,从而破坏了其他优秀程序员的声誉.

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

key*_*one 33

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

简单的例子:

require 'digest/sha1'
Digest::SHA1.hexdigest("some string")
Run Code Online (Sandbox Code Playgroud)

  • 没错,但SHA1和MD5是否过度杀伤?太慢了? (3认同)
  • @RobDavis #hexdigest中的"hex"表示输出是十六进制数,要将其转换为int,您只需要调用to_i(16) (2认同)

Jas*_*son 6

最简单(且一致)的方法可能是这样(而且速度很快):

"https://www.example.com/abc/def/123?hij=345".sum % 4
Run Code Online (Sandbox Code Playgroud)

这总是会产生一个整数 0 - 3,速度相当快,并且应该分布得相当好(尽管我实际上还没有对分布进行测试)。