Php 用于负载平衡的哈希算法

Php 用于负载平衡的哈希算法,php,load-balancing,Php,Load Balancing,重要信息:在建议我们使用现成的负载平衡器之前,请了解我们并不是在尝试负载平衡正常的internet流量。我们从许多来源接收数据,其中一些来源没有连接到互联网(例如,他们可能使用短信或类似方式)。我们处理这些信息,然后将其转发到下一阶段。这是我们需要实现负载平衡的内部步骤它没有使用HTTP请求 现在的情况是: 我正在对PHP中用于负载平衡的各种哈希算法进行测试。我需要保证每个设备都在同一个节点上实现负载平衡。在我们的用例中,每条消息都有一个恒定的序列号,所以我计划使用这个值。来自给定设备的所有消息

重要信息:在建议我们使用现成的负载平衡器之前,请了解我们并不是在尝试负载平衡正常的internet流量。我们从许多来源接收数据,其中一些来源没有连接到互联网(例如,他们可能使用短信或类似方式)。我们处理这些信息,然后将其转发到下一阶段。这是我们需要实现负载平衡的内部步骤它没有使用HTTP请求

现在的情况是:

我正在对PHP中用于负载平衡的各种哈希算法进行测试。我需要保证每个设备都在同一个节点上实现负载平衡。在我们的用例中,每条消息都有一个恒定的序列号,所以我计划使用这个值。来自给定设备的所有消息在同一节点上进行负载平衡是至关重要的。此时,我们对节点容量不感兴趣

所以,我读了一些关于使用散列的模等来确定指向哪个节点的文章。我看到一些人说,MD5、SHA1、SHA256和SHA512中哈希的十进制表示都将超过
PHP\u INT\u MAX
,因此模数将始终为零,因此我们不能使用它来实现负载平衡

我还看到一些建议,我们可以简单地将散列的一大块进行位移位,只使用高位来获得模数,然后再次使用它

这让我想知道。。。由于我们只需要在数量相对较少的节点之间进行负载平衡即可开始(在一段时间内不会超过16个节点),因此是否有任何算法足以让我们仅使用第一个字节并在此基础上进行负载平衡

所以我写了一个非常简单的函数:

function balanceToNode(string $serial, string $algo="md5", int $nodes=1)
{
    $hash = hash($algo, $serial);
    return hexdec($hash[1]) % $nodes;
}
我使用
md5
sha1
sha256
sha512
对我们数据库中1000个真实序列号的样本进行了测试。我分别测试了4个、8个和16个节点,并检查了每个节点的标准偏差

单字节测试 我发现使用
md5
可以在节点之间生成可预测且平衡良好的数据,而不管我们使用了多少节点<如果节点数量较少,则代码>sha1的平衡性较差,但如果节点数量较多,则平衡性更好
sha256
甚至比
sha1
更差,但在节点数量较多的情况下仍能更好地平衡,
sha512
几乎不受节点数量的影响,但仍不如
md5
平衡

这是我们从测试中得到的实际数据。我们从样本中提取一个估计的标准偏差,得到每个节点的数量,然后计算总体的stdev,得到算法一致性的数字。我可能数学做错了!在所有情况下,我都在寻找较小的数字

MD5
  • 4节点:8.041558721
  • 8节点:7.171371656
  • 16节点:7.554248253
一致性:0.356104153

沙一
  • 4节点:17.53092506
  • 8节点:13.24494513
  • 16节点:7.966596931
一致性:3.91162024

SHA256
  • 4节点:25.81988897
  • 8节点:15.7116881
  • 16节点:11.40741718
稠度:6.04080998

SHA512
  • 4节点:11.5758369
  • 8节点:10.87592361
  • 16节点:9.535897091
一致性:0.846358482

8字节测试 我再次运行了测试,这次使用任何给定哈希的前8个字节。这带来了巨大的不同,尽管md5仍然表现得最好。在这里,让我感到惊讶的是,
sha512
在16岁时的表现明显比在8岁时差

MD5
  • 4个节点:18
  • 8节点:13.53302838
  • 16节点:7.916228058
一致性:4.12559407

沙一
  • 4节点:27.41046029
  • 8节点:17.63114128
  • 16节点:8.181279444
一致性:7.850664268

SHA256
  • 4节点:25.31139401
  • 8节点:15.25029274
  • 16节点:7.509993342
一致性:7.287949408

SHA512
  • 4节点:17.60681686
  • 8节点:6.886840453
  • 16节点:11.44261042
一致性:4.39280188

我的实际问题 请记住,我们使用哈希算法纯粹是为了在节点集群中分发消息,而不是为了保护密码。此外,根据样本,问题如下:

  • 仅使用第一个字节安全吗
  • 可以使用
    md5
  • 我的数学错了吗

  • 如果序列号具有均匀随机分布,请使用

    n=序列号%n

    其中n是要寻址的节点,n是节点总数


    随着使用的序列越来越多,通过使用一些中间位而不是这个简单公式中的最低位,可以更好地平衡负载。CPU缓存通常以这种方式运行。但是这种额外的复杂性可能值得,也可能不值得。大多数负载平衡器都允许您将来自给定客户端的所有请求映射到单个后端服务器。您可能应该选择一个负载平衡器并阅读它的文档;客户端是我们自己的接收器,设备不是典型的web浏览器。他们没有一致的IP,不支持cookies。。。有些甚至不是IP连接的设备。我们接收它们,处理消息,然后将其转发到下一步,这就是我们在这里尝试的负载平衡,所以它们是你的接收者?您是否无法将请求处理为可预测的内容,如X-DEVICE-ID标头或类似内容?老实说,我不会在PHP中实现这个逻辑,它肯定会很慢。场景是数千(可能是数百万)个设备拨入接收器软件,有时是通过互联网,有时不是。每个设备都报告一个序列号。使用这些序列号,我希望负载平衡进入下一个阶段,目前是一个单一的实例。我只使用PHP