Высокие нагрузки

Статус
В этой теме нельзя размещать новые ответы.

phillip

Полезный
Регистрация
4 Сен 2007
Сообщения
411
Реакции
15
Сделал для доргена модуль. Юзер заходит на сайт, тогда модуль "на лету" через fopen() открывает файл с ключами, и вставляет рендомные строки. в файле 200к строк. Но считываем мы не все, а именно рендомные. fseek, затем fgets. когда 15к запросов идет, все падает. как оптимизировать?
 
А как вы узнаёте кол-во строк в файле? Или скрипту заранее известно это количество?

Если можно, лушче сопроводить вопрос примером кода. Если скрипт сам узнаёт кол-во строк каждый раз - это будет ооочень тормозить. Если заранее известно и надо только считывать интервалы байтов, то будет быстрее.

По-уму надо всё хранить в памяти, но на шаред хостинге такой роскоши нет. Советую каждую операцию заключить в microtime(true) и посмотреть где именно существует узкое место. Если узкое место явно не наблюдается, то надо думать дальше.
 
окей! спасибо за ответ!
ну во-первых скрипт поделен на две части, клиентскую и серверную. Собственно, юзер заходит на клиентскую часть, и в файле идет курлом примерно такой вызов:
PHP:
$query_str = 'mod=warez&mod_keys='.$mod_keys.'&one_key=true&klient_domen='.$klient_domen.'&module_path='.$module_path;
$ch = curl_init();  
curl_setopt($ch, CURLOPT_URL,$dorgen_adr.'mod-reqs.php');  
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_str); 
$res = curl_exec($ch); 
curl_close($ch);
$content= preg_replace('/'.$t.'/', $res, $content, 1);
Это собственно чего означает. Курлом посылаем запрос на серверную часть, ответ от серверной части вставляем в контент страницы. А ответ представляет собой список линков. То есть... Вот примерно серверная часть:
PHP:
if (isset($_POST['mod']) and $_POST['mod']=='warez' and isset ($_POST['c_lnks'])) {

$f = fopen('doors_datas/keywords/'.$_POST['mod_keys'].'.txt',  'r');
$sz= filesize('doors_datas/keywords/'.$_POST['mod_keys'].'.txt');

for ($x=0; $x<$_POST['c_lnks']; $x++) {
fseek($f, rand(0, $sz)); fgets($f);
$k=trim(fgets($f));
echo '<a href="http://'.$_POST['klient_domen'].'/'.$_POST['module_path'].'/'.urlencode($k).'.html">'.$k.'</a><br />'; 
}
fclose($f);
}
Вкратце, что это за механизм. Нам переданы POST данные, с указанием названия текстового файла. Этот файл открываем через fopen, далее получаем его размер через filesize и потом сперва берем обрывок строки с рендомным смещением fseek($f, rand(0, $sz)); и тут же берем целую строку fgets($f); Таким образом, незамысловато набираем набор рендомных строк из файла.
Очень прошу помочь, работает медленно!
 
окей! спасибо за ответ!
ну во-первых скрипт поделен на две части, клиентскую и серверную. Собственно, юзер заходит на клиентскую часть, и в файле идет курлом примерно такой вызов:
PHP:
$query_str = 'mod=warez&mod_keys='.$mod_keys.'&one_key=true&klient_domen='.$klient_domen.'&module_path='.$module_path;
$ch = curl_init();  
curl_setopt($ch, CURLOPT_URL,$dorgen_adr.'mod-reqs.php');  
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_str); 
$res = curl_exec($ch); 
curl_close($ch);
$content= preg_replace('/'.$t.'/', $res, $content, 1);
Это собственно чего означает. Курлом посылаем запрос на серверную часть, ответ от серверной части вставляем в контент страницы. А ответ представляет собой список линков. То есть... Вот примерно серверная часть:
PHP:
if (isset($_POST['mod']) and $_POST['mod']=='warez' and isset ($_POST['c_lnks'])) {
$f = fopen('doors_datas/keywords/'.$_POST['mod_keys'].'.txt',  'r');
$sz= filesize('doors_datas/keywords/'.$_POST['mod_keys'].'.txt');
for ($x=0; $x<$_POST['c_lnks']; $x++) {
fseek($f, rand(0, $sz)); fgets($f);
$k=trim(fgets($f));
echo '<a href="http://'.$_POST['klient_domen'].'/'.$_POST['module_path'].'/'.urlencode($k).'.html">'.$k.'</a><br />'; 
}
fclose($f);
}
Вкратце, что это за механизм. Нам переданы POST данные, с указанием названия текстового файла. Этот файл открываем через fopen, далее получаем его размер через filesize и потом сперва берем обрывок строки с рендомным смещением fseek($f, rand(0, $sz)); и тут же берем целую строку fgets($f); Таким образом, незамысловато набираем набор рендомных строк из файла.
Очень прошу помочь, работает медленно!

В серверном скрипте работай с БД. Будет быстрее файла.

Если ты на *nix, то попробуй:

PHP:
function getFileLine($file, $line) {
    return trim(exec("head -n $line $file | tail -n 1"));
}

но учти, что при 15к запросов это не спасет. Так что остается БД
 
пробовал с бд, мускулем родным. что-то тоже медленно. Наверно я как-то примитивно делаю. а мб в оперативке держать? 400мб доступно
 
Самое узкое место (помимо сети и чтения файла) - это rand() Смею предположить, что из БД вы вытягивали данные путём такого запроса:
Код:
SELECT * FROM keys ORDER BY RAND() LIMIT x
? это будет выполняться ооочень медленно из-за ORDER BY RAND(), надо использовать другие методы.

И не советую использовать обычный rand() тут я писал почему:
Скрытое содержимое доступно для зарегистрированных пользователей!
(т.к. он вовсе не случаен)
 
в этом скрипте у меня с бд ничего не связано как раз. насчет rand- я всегда пользовал mt_rand, а тут как-то так вышло, сам не заметил. А в остальном, кроме rand?
тему посмотрел, хорошо описано, спасибо
 
А что ещё можно сделать? Можно большой файл разбить на несколько маленьких, но мне кажется, это ничего не даст. Других методов извлечения строк из файла нет. Ваш метод немного избыточен из-за лишнего вызова fgets(), но я думаю строк читается не много и это не сильно накладно. Когда речь идёт о высоких нагрузках, значение имеет абсолютно любая мелочь.

Если хранить всё в памяти, то нужно использовать key-value БД вроде APC или memcached или Redis. Mysql при правильном подходе тоже должен быстро справляться.

А ваш rand() будет генерить одинаковые страницы (одни и те же кеи будет вытаскивать) т.е. одну и ту же последовательность.
 
А ваш rand() будет генерить одинаковые страницы (одни и те же кеи будет вытаскивать) т.е. одну и ту же последовательность.
ну да. исходя из вашей статьи на которую дали линк, я это понял. Изменю.
А насчет memcache и APC. скрипт надо будет сильно переделывать? или их просто включаешь и все, все само собой работает? Мб где-то есть наглядный мануал как их использовать. Поискал- все в основном освещают темы по типу "мемкеш сравнили с APC, мемкеш хорош потому-то, а этот вот поэтому". А конкретная инструкция что измени скрипт вот так, чтобы было круто. нема :nezn:
Давно увиливал от этой темы, но похоже без этих самых мемкеш и APC не обойтись
 
Использовать просто. Достаточно открыть мануал по PHP, там всё есть.
PHP:
$lines = apc_get( 'dorgen_lines_cnt' );
$r = rand( 0, $lines );
$randomLine = apc_get( 'dorgen_line_' . $r );
У остальных примерно такой же API. Тут всё зависит от того какой у вас сервер. Я бы на вашем месте всё же попробывал MySQL т.к. он работает очень быстро. Самое узкое место будет подключение и возможно переполнение допустимого кол-ва открытых соединений, можно, но очень не рекомендуется использовать постоянные соединения. Можно получить 100 запросов в секунду. Что для этого нужно:
1) Таблица со строками myisam с автоинкрементным полем без дырок (все записи должны идти по порядку)
2) Нужно знать сколько строк всего.
3) В PHP генерируете массив случайных чисел и вставляете в запрос
Код:
SELECT `line` FROM `dorgen_lines` WHERE `id` IN ( 1, 15, 23, 234, 53 )
И если и это бы тормозило, я бы поставил Sphinx search у него индексы ещё быстрее.

Добавлено через 1 минуту
P.S. в майскул можно использовать тип таблиц мемори - будет всё храниться в памяти (до перезагрузки сервера).
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху