Yvision.kz
kk
Разное
Разное
399 773 постов42 подписчика
Всяко-разно
0
20:59, 11 сентября 2010

Как делался счётчик посещений на iNternets.kz

В продолжение предыдущего поста Асинхронность PHP сегодня я расскажу, как применялись эти знания на практике.

Больше двух лет назад впервые увидел свет очередной мой проект - каталог казахстанских сайтов iNternets.kz. Тогда это действительно был только каталог сайтов, но очень быстро пришло понимание того, что такой сайт не особо интересен нашим веб-мастерам и недостаточно конкурентоспособен. Я начал обвешивать его дополнительными функциями - проверка ТИЦ и PR, оценка семантичности вёрстки и, как естественное продолжение каталога сайтов - система статистики.

Изначально было принято решение, что основным станет невидимый счётчик, а графический будет опцией и размещение любого счётчика (как и обратной ссылки) будет сугубо добровольным.

Первая версия счётчика производила запись в таблицу MySQL напрямую, из этой же таблицы с помощью чудовищных COUNT'ов и группировок вытаскивались отчёты. Когда я разместил этот счётчик на двух сайтах, посещаемостью 2000 уникальных визитов в сутки, время ответа скрипта счётчика составило больше секунды, а отчёты создавались за 8-10 секунд. Отвратительно.

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

В третьей версии решено было сделать счётчик асинхронным - общий по всем сайтам лог посещений записывался в базу SQLite, а cron-скрипт раз в минуту разбирал её и обновлял таблицы в MySQL'е. Это позволило сильно ускорить генерацию счётчика и я расхрабрился настолько, что установил его на сайт с ежедневной посещаемостью около 20 000.

Этот шаг вскрыл ещё одну проблему. Теперь за выделенную минуту не успевала обрабатываться очередь в SQLite-базе. Не спасала блокировка с помощью pid-файла: очередь росла быстрее, чем скрипт её обрабатывал.

Чтобы решить эту проблему, я стал записывать посещения в 10 разных файлов по схеме:
$db_filename = (time() %10) . ".log";
А обработку очереди я разделил на 10 независимых "потоков" (потоками в полном смысле этого слова такое решение назвать никак нельзя, но и полноценные потоки здесь, в принципе, не нужны):

$dh = opendir($counter_log_dir);
while($file = readdir($dh)) {
if(preg_match("/\.log$/i", $file)) {
system("php -q counter_thread.php " . $file)
}
}
closedir($dh);

Теперь очередь успевает обработаться за минуту, в отчётах всегда актуальные данные, но встала проблема с хостингом. Хостер активно урезает проекту CPU, так что следующим шагом будет переход на VPS или хотя бы отселение на отдельный аккаунт (сейчас рядом с iNternets'ами проживает достаточно прожорливый новостной сайт, о котором я, может быть, расскажу в следующих постах).

0
400
4