用于负载平衡的哈希算法

时间:2016-01-26 15:01:42

标签: php load-balancing

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

现在的情景:

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

因此,我已经阅读了一些关于使用散列等模数来确定要指向哪个节点的文章。我已经看到一些说明来自MD5,SHA1,SHA256和SHA512的散列的十进制表示都将超过PHP_INT_MAX,因此模数将始终为零,因此我们无法使用它来负载平衡。

我也看到过一些建议,我们可以简单地将一小部分哈希值移开并仅使用高位来获得模数,然后再使用它。

这让我感到疑惑......因为我们只需要在相对较少数量的节点之间进行负载平衡(它在一段时间内不会超过16),所以任何算法都足够我们可以使用第一个字节和负载平衡基于那个?

所以我写了这个非常简单的功能:

function balanceToNode(string $serial, string $algo="md5", int $nodes=1)
{
    $hash = hash($algo, $serial);
    return hexdec($hash[1]) % $nodes;
}

我使用md5sha1sha256sha512针对来自我们数据库的1000个真实序列号的样本运行此操作。我用4,8和16节点测试每个节点,并检查每个节点的标准偏差。

单字节测试

我发现使用md5导致节点之间的数据可预测且平衡良好,无论我们使用多少个节点。如果我们有少量节点,sha1平衡性很差,但节点数量较多时平衡性更好。 sha256甚至比sha1更差,但仍然可以更好地与更多节点保持平衡,sha512几乎不受节点数量的影响,但仍然没有{{1} }}

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

MD5

  • 4个节点:8.041558721
  • 8个节点:7.171371656
  • 16个节点:7.554248253

一致性:0.356104153

SHA1

  • 4个节点:17.53092506
  • 8个节点:13.24494513
  • 16个节点:7.966596931

一致性:3.91162024

SHA256

  • 4个节点:25.81988897
  • 8个节点:15.7116881
  • 16个节点:11.40741718

一致性:6.040803998

SHA512

  • 4个节点:11.5758369
  • 8个节点:10.87592361
  • 16个节点:9.535897091

一致性:0.846358482

8字节测试

我再次运行测试,这次使用来自任何给定哈希的前8个字节。尽管md5仍然表现最佳,但这有很大的不同。对我来说,最令我惊讶的是,md5表现得更差16,而不是8

MD5

  • 4个节点:18
  • 8个节点:13.53302838
  • 16个节点:7.916228058

一致性:4.12559407

SHA1

  • 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

我的实际问题

请记住,我们使用哈希算法PURELY在节点集群中分发消息,而不是保护密码。此外,根据样本,问题是:

  1. 我可以安全地使用第一个字节吗?
  2. 使用sha512
  3. 是否可以
  4. 我的数学错了吗?

1 个答案:

答案 0 :(得分:0)

如果您的序列号具有统一的随机分布,请使用

n =序列%N

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

使用更多的序列号时,通过使用一些中间位而不是最简单的公式,可以更好地平衡负载。 CPU缓存通常以这种方式运行。但是这种额外的复杂性可能或者可能不值得付出努力。