【问题标题】:Hash algorithms for load balancing用于负载平衡的哈希算法
【发布时间】:2016-01-26 15:01:42
【问题描述】:

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

现在的场景:

我正在对 PHP 中的各种散列算法进行一些测试,以用于负载平衡。我需要保证每个 device 负载均衡到同一个节点。在我们的用例中,每条消息都有一个恒定的序列号,所以我打算使用这个值。将来自给定设备的所有消息负载平衡到同一节点至关重要。我们目前对节点容量不感兴趣。

所以,我已经阅读了一些关于使用哈希模数等来确定要定向到哪个节点的文章。我看到有人说 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 几乎不受节点数量的影响,但仍不如 md5 平衡。

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

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 似乎仍然表现最好,但这带来了巨大的变化。对我来说最大的惊喜是sha512 在 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

我的实际问题

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

  1. 只使用第一个字节是否安全?
  2. 可以用md5
  3. 我做错数学了吗?

【问题讨论】:

  • 大多数负载均衡器允许您将来自给定客户端的所有请求映射到单个后端服务器。您可能应该选择一个负载均衡器并阅读它的文档。
  • 在我们的案例中不实用;客户端是我们自己的接收者,设备不是典型的网络浏览器。它们没有一致的 IP,不支持 cookie……有些甚至不是 IP 连接设备。我们接收它们,处理消息,然后将其转发到下一步,这就是我们在这里尝试进行负载平衡的内容
  • 所以他们是你的接收者?您是否无法将请求操纵到可预测的内容,例如 X-DEVICE-ID 标头或类似内容?老实说我不会在 PHP 中实现这个逻辑,它一定会很慢。
  • 这种情况是成千上万(可能是数百万)设备拨入接收器软件,有时通过互联网,有时不通过。每个设备都报告一个序列号。使用这些序列号,我想将负载平衡到下一个阶段,目前是单个实例。我只使用 PHP 来测试一些数学,因为它支持快速开发,因此非常适合原型设计
  • 序列号是怎么传的?

标签: php load-balancing


【解决方案1】:

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

n = 序列 % N

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

使用更多的串行,通过使用一些中间位而不是这个简单公式的最低位可以更好地平衡负载。 CPU 缓存通常以这种方式运行。但这种额外的复杂性可能值得,也可能不值得。

【讨论】:

  • 连续剧没有均匀的随机分布。我们也无法控制它们。这就是我尝试哈希的原因
  • 然后先检查简单、易于计算的东西(CRC32、Adler 等)。仅对哈希码使用密码学似乎有些矫枉过正。我们需要随机性,而不是安全性。
  • 这就是我们首先查看 MD5 和 SHA1 的原因;快速校验和哈希。也可以试试 CRC,看看是否能提供足够的分布。
  • 哦,郑重声明,一百万年后,我绝不会将 MD5 或 SHA1 放在“密码学”桶中
猜你喜欢
  • 1970-01-01
  • 2014-01-04
  • 2017-04-20
  • 1970-01-01
  • 2014-02-04
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
相关资源
最近更新 更多