Учет статистики, как лучше организовать при большой нагрузке

JIEXA

Новичок
Учет статистики, как лучше организовать при большой нагрузке

Имеем таблицы MySQL тип innoDB
stat_tizers
stat_id
stat_date
tiz_id
tiz_hits
tiz_clicks

stat_sites
stat_id
stat_date
site_id
site_hits
site_clicks

Есть скрипт, скажеж view.php
К котрому может быть до 1 тыс обращений в секунду.
При его запуске должно в таблице stat_tizers обновится значение поля tiz_hits на +1 у нескольких полей. (все зависит от того, сколько тизеров запрошено)
И у таблицы stat_sites должно обновится значение site_hits на +N (N - кол-во запрошеных тизеров)
Покажу запрос для наглядности
UPDATE stat_tizers SET tiz_hits=tiz_hits+1 WHERE stat_date = NOW() AND tiz_id IN ('4', '7', '9')
UPDATE stat_sites SET site_hits=site_hits+3 WHERE stat_date = NOW() AND site_id = '1'

Также есть скрипт clicks.php
К нему обращения происходят намного реже, не больше 50-100 в секунду
Его действия примерно теже, что и у view.php, только обновляет он поле site_clicks

Суть вопроса:
При таком большом кол-ве запросов, серверу будет трудновато.
Поэтому я думаю над тем, как можно увеличить производительность.
Есть вариант 1.
Создать копии этих тоблиц, но уже с типом MEMORY и раз в минуту синхронизировать их скриптом, который будет запускаться по крону
Тут тоже есть свои минусы - в момент синхронизации, в MEMORY таблицы нельзя будет писать, так как иначе нарушится целостность данных.

Вариант 2.
Писать тупо лог в 2 файла
В первый - по четным минутам, во второй по нечетным
И раз в четную минуту запускать скрипт, который бует парсить лог нечетной минуты, а в нечетную наоборот парсить лог четной минуты.
То есть пока один парсится, в другой инфа сохраняется.
Решение мне впринципе нравится, но с маштабированием его будут проблемы, на несколько серверов данную операцию не расскидаешь.

Вобщем я в тупике. Ребят, подскажите, может я не с той стороны смотрю на вопрос. Как лучше реализовать это?
Заранее огромное спасибо.
 

antson

Новичок
Партнер клуба
>Писать тупо лог
не писать , а настроить лог апача или nginx , чтобы в него
попадала все нужная информация.

-~{}~ 15.04.09 08:30:

Вообщето под такую стартовую нагрузку нужно уже больше одного сервера : фронт - несколько беков - сервер СУБД,
и писать так, чтобы можно было линейно наращивать производительность добавлением беков.
 

Dovg

Продвинутый новичок
Писать тупо лог в 2 файла
В первый - по четным минутам, во второй по нечетным
И раз в четную минуту запускать скрипт, который бует парсить лог нечетной минуты, а в нечетную наоборот парсить лог четной минуты.
То есть пока один парсится, в другой инфа сохраняется.
На самом деле два лога не нужно.
Пишешь в один, его же обрабатываешь, запоминая как-нибудь последнюю обработанную строчку.
Если нечего обрабатывать - молча умираешь
как только лог сротировался, сбрасываешь счетчик строчек

не писать , а настроить лог апача или nginx , чтобы в него
попадала все нужная информация.
+1
 

DiMA

php.spb.ru
Команда форума
Если писать в файлы, то их нужно штук 10-100 завести, писать в случайный по рандому, т.к. при записи необходима блокировка всего файла, что можно тормознуть другие копии. Писать текст без блокировки - 100% порча файла.

> Пишешь в один, его же обрабатываешь, запоминая как-нибудь последнюю обработанную строчку.

Чушь. Во-первых, от параллельных блокировок при записи все затормозится, во-вторых после обработки крон-скриптом файл нужно полность очистить.

Причем тут лог апача? Скрипт должен писать в лог не просто свой адрес, а еще кучу полезных парамеров: username, имя раздела и прочие полезные данных.
 

Макс

Старожил PHPClub
имхо достаточно в имя лог-файла добавить текущую минуту:
$log_filename = '/logs/stats'.date('Ymd-hi').'.log'; - примерно так

И скриптом-парсером обрабатывать только старые лог-файлы (больше минуты назад созданые)

насколько я помню, на добавление записи в файл не нужно блокировать, если размер добавляемой записи не слишком большой.
 

Dovg

Продвинутый новичок
а я померял )
100 потоков, каждый записывает по 10000 строчек в файл (в один и тот же)
Код:
time bash ./block_test.sh

real    0m27.061s
user    0m17.037s
sys     0m31.678s
Миллион записей за 30 секунд или 30000 записей в секунду.

Код:
#!/bin/bash
	
	i=0
	
	while [ true ]; do
	
		i=$((i+1))
		
		php ./block_test.php &
		
		if [ $i -ge 100 ] ; then
			break;
		fi
	
	done
	
	while [ true ]; do
		
		if [ 1 -ge $(ps aux | grep -c block_test.php) ] ; then 
			exit
		fi
		
	done
PHP:
<?php
	define('FILE_NAME', '/tmp/block.test');
	
	for ($i = 0; $i < 10000; $i++)
		file_put_contents(FILE_NAME, md5(microtime(true))."\n", FILE_APPEND);
?>
 

DiMA

php.spb.ru
Команда форума
> Для чего?

веб-скрипты скинули в лог кучу г*вна со статистикой
она нужна только для функционирования отложенной очереди записи в базу
как только крон (ежеминутный скрипт) прочитал текст - файл более не нужен, чиститься

> а я померял )

Напиши по-русски, чего ты померял и как решать задачу оптимальнее.


>define('FILE_NAME', '/tmp/block.test');
> for ($i = 0; $i < 10000; $i++)
> file_put_contents(FILE_NAME, md5(microtime(true))."\n", FILE_APPEND);

это чушь какая-то... Ты вообще о чем, тему читал?

статистика в файл пишется так:

f=fopen(filename, "a+") or ...
fblock(...) or ...
fputs(...)
fclose()
 

JIEXA

Новичок
Но ведь как я писал в первом посте, при записи в файл мы лишаемся маштабируемости

И как сказал DiMA использовать nginx или апач для сохранения логов не вариант - так как некоторые параметры, которые нужно записывать, получаются в ходе выполнения скрипта.

А что скажите насчет БД, как её тут можно грамотнее использовать?
 

phprus

Moderator
Команда форума
JIEXA
использовать nginx или апач для сохранения логов не вариант - так как некоторые параметры, которые нужно записывать, получаются в ходе выполнения скрипта.
Почему не вариант? Скрипт-же может отдавать эти данные заголовками, а nginx будет писать их в лог(переменные $upstream_http_*) и попутно запрещать передачу их клиенту (директивы fastcgi_hide_header и proxy_hide_header).

А дальше nginx умеет переоткрывать логи по сигналу, те можно либо переименовывать логфайл, заставлять nginx переоткрыть логи и делать что угодно с переименованным логом либо запоминать последнюю обработанную позицию в логе и читать с нее.
 

Alexandre

PHPПенсионер
я статистику скидываю скриптом в лог-файл
каждые 15-30 мин я забираю лог и гружу его в БД
для статистики лучше грузить в отдельную БД

как утвержадали выше, проще настроить лог самого WEB сервера
но я сделал проще - написал маленький модуль который сам пишет в лог необходимую информацию
модуль работает в проекте по учету банерных показов и переходов, но пока там нагрузка не высокая: но мы верим что число клиентов нашего сайта вырастет и нагрузки на сервак увеличится
 

Dovg

Продвинутый новичок
статистика в файл пишется так:

f=fopen(filename, "a+") or ...
fblock(...) or ...
fputs(...)
fclose()
в чем приципиальное отличие от file_put_contents(FILE_NAME, ..., FILE_APPEND | LOCK_EX);

?

по теме:
можно писать в базу, в отдельные таблицы, insertом, из ключей только primary_key

в остальном все тоже самое - обработали пачку и грохнули.
 

Макс

Старожил PHPClub
Но ведь как я писал в первом посте, при записи в файл мы лишаемся маштабируемости
тогда вместо файлов можно использовать message queue сервера.
Beanstalkd например. Зависит от твоих потребностей.
А что скажите насчет БД, как её тут можно грамотнее использовать?
грамотно - не писать в них в realtime
 

Alexandre

PHPПенсионер
можно писать в базу, в отдельные таблицы, insertом, из ключей только primary_key
перед вставкой ключи надо отключать

-~{}~ 15.04.09 13:58:

Но ведь как я писал в первом посте, при записи в файл мы лишаемся маштабируемости
вот этого я как раз не понял?
есть два (три, пять) сервера - пишем в каждом сервере в свой лог, потом делаем вставку в единую БД. Информация не теряется
почему мы лишаемся масштабируемости?

-~{}~ 15.04.09 14:02:

вообще, чтоб избежать локов необходимо переименовывать лог-файлы и парсить уже переименованный файл, а затем его уничтожать (хотя нет в этом необходимости) .
информация не теряется
 

DiMA

php.spb.ru
Команда форума
> в чем приципиальное отличие от file_put_contents(FILE_NAME, ..., FILE_APPEND | LOCK_EX);

да, ничем, невнимательно читал

маштабируемость никак не страдает, ибо собирать эти файлы можно откуда угодно по сети, каким угодно обработчиком и когда угодно (с задержками)
 

Sherman

Mephi
Автор оригинала: Макс
насколько я помню, на добавление записи в файл не нужно блокировать, если размер добавляемой записи не слишком большой.
Совершенно верно, если файл открыт с флагом o_append.
 
Сверху