Хорошо, название действительно очень субъективное.Но это как раз то, в чем проблема для меня.
Предпосылкой является то, что я хочу равномерно распределять попадания статического веб-содержимого на определенное количество серверов кэширования.Кроме того, доставка клиентам должна быть ускорена, поскольку несколько доменов используются, а запросы не блокируют друг друга.Мне также не нужен классический балансировщик нагрузки, но я сразу генерирую правильные ссылки в моем HTML-коде.
Я также хочу убедиться, что один и тот же URL-адрес всегда обслуживается одним и тем же сервером.
Итак, я только что определил небольшую функцию, которая возвращает хост для использования путем хэширования URL-адреса запроса и вычисляет по модулю количество используемых серверов:
function pseudocode_statify($url) { // $url looks like /folder1/folder2/file.jpg
return 'http://' . md5($url) % $num_of_servers .'.mydomain.com' . $url;
}
Сначала у меня было что-то вроде шестнадцатеричного декодирования и подстроки кпредотвратить переполнение на месте, но обнаружил, что он просто отлично работает, как описано выше.
Однако моя проблема заключается в том, что, если я запускаю следующий тестовый скрипт:
for($i=0;$i<100000;$i++) {
$md5 = md5(uniqid($i).microtime().rand(1,999999999999));
$result[$md5%2]++;
}
Я ожидал равномерного распределения,это означает, что $ result [0] будет около значения $ result [1];
Это не тот случай.
Ладно, ничего особенного, софар.Я бы просто принял тот факт, что md5 распределен не так равномерно, как я думал, и использовал бы другой алгоритм хеширования, например, sha1 или что-то в этом роде.
Но я попытался воспроизвести результаты и нашел образец, который не могуобъясните.
Соотношение всегда было около 2/1.На самом деле это соотношение всегда было что-то вроде 1 / 2,16 к 1 / 2,17
Пример вывода некоторых запусков приведенного выше сценария:
output was generated by: echo "ratio: ".$result[0]/$result[1]."\n";
ratio: 2.1757121534504
ratio: 2.1729411578062
ratio: 2.1726559360393
ratio: 2.1676895664225
ratio: 2.1667416128848
ratio: 2.1667115284133
ratio: 2.1677791605385
ratio: 2.1658969579688
ratio: 2.1668508131769
ratio: 2.1689292821741
Теперь странным было то, что отношение сумм% 2, равных 1 и сумм% 2, равных 0 , иногда чередуются!
for($j = 0; $j<100;$j++) {
for($i=0;$i<100000;$i++) {
$md5 = md5(uniqid($i).microtime().rand(1,999999999999));
$result[$md5%2]++;
}
var_dump($result);
}
Я запускал скрипт из командной строки два раза подряд и прерывал егопосле 3 прогонов получилось два выхода:
joe@joe-laptop:/home/flimmit/httpdocs$ php test.php
PHP Notice: Undefined variable: result in /home/flimmit/httpdocs/test.php on line 6
PHP Notice: Undefined offset: 0 in /home/flimmit/httpdocs/test.php on line 6
PHP Notice: Undefined offset: 1 in /home/flimmit/httpdocs/test.php on line 6
array(2) {
[0]=>
int(68223)
[1]=>
int(31777)
}
array(2) {
[0]=>
int(136384)
[1]=>
int(63616)
}
array(2) {
[0]=>
int(204498)
[1]=>
int(95502)
}
^C
joe@joe-laptop:/home/flimmit/httpdocs$ php test.php
PHP Notice: Undefined variable: result in /home/flimmit/httpdocs/test.php on line 6
PHP Notice: Undefined offset: 1 in /home/flimmit/httpdocs/test.php on line 6
PHP Notice: Undefined offset: 0 in /home/flimmit/httpdocs/test.php on line 6
array(2) {
[1]=>
int(31612)
[0]=>
int(68388)
}
array(2) {
[1]=>
int(63318)
[0]=>
int(136682)
}
array(2) {
[1]=>
int(94954)
[0]=>
int(205046)
}
^C
joe@joe-laptop:/home/flimmit/httpdocs$
Как видно из первого, первый результат результатов всегда выше, а во второй наоборот.тот же сценарий.
Странно то, что я могу ТОЛЬКО воспроизвести это поведение, когда я запускаю сценарий несколько раз.
Я написал этот небольшой сценарий, чтобы воспроизвести «свопинг» и сгенерировать достаточно данных измерения:
for($j = 0; $j<100;$j++) {
for($i=0;$i<rand(1000,10000);$i++) {
$md5 = md5(uniqid($i).microtime().rand(1,99999999));
$result[$md5%2]++;
}
#var_dump($result);
echo "ratio: ".$result[0]/$result[1]." ".(($result[0]<$result[1]) ? "A":"B")."\n";
sleep(rand(2,5));
}
Но здесь Он печатает только b, а не A.Это заставило меня подумать, что в сценарии может быть семантическая ошибка, но я ее не нашел.
Я действительно застрял, и это меня очень беспокоит.
Итак, мои вопросы:
Можете ли вы порекомендовать любую литературу / веб-ссылки, где я мог бы прочитать немного больше о md5, включая дистрибутивы и т. Д.
Можете ли вы объяснить / воспроизвести поведение?У меня есть ошибка здесь?(на самом деле это очень вероятно, но я не могу его найти)
Можете ли вы порекомендовать какой-либо другой алгоритм, который подходит для моего варианта использования?Он не должен быть криптографическим или сильным, но быстрым, детерминированным и равномерно распределенным.