company_banner

Способы подсчета статистики посещения страниц сайта «на лету»

    Часто возникает задача подсчета количества посещений той или иной страницы портала или подсчета кликов по какой-то ссылке. Например. может быть интересно подсчитать количество просмотров статьи или объявления, число кликов по «показать номер телефона» на странице объявления о продаже и т.д. и т.п.

    Главное точно понимать, для чего вы планируете использовать эти счетчики и для чего они могут понадобиться в обозримом будущем. Нужно ли по ним выбирать/сортировать/группировать сущности или вам просто нужны редкие разовые отчеты (например раз в сутки)? А может, вы хотите показывать эти счетчики в админке или в личном кабинете пользователя? Хотите ли вы в реальном времени показывать эти числа или можно ограничиться часовой/суточной отсечкой? В зависимости от этих и, возможно, еще каких-то критериев будет зависеть выбор способа подсчета и хранения счетчиков.

    Подсчет кликов/визитов

    Задачу подсчета кликов/визитов можно решать разными способами:
    • при посещении страницы или при обращении к какому-то URL делать +1 к счетчику;
    • периодически просматривать логи Web-сервера и считать число обращений к нужным URL-ам;
    • делать через redirect со специального URL-а, и перед редиректом делать +1 (но это, как вы понимаете, работает не во всех случаях);
    • с помощью JavaScript обращаться к URL счетчика при каком-то событии;
    • другие способы, на которые хватит фантазии.


    На данном этапе необходимо решить, нужно ли нам считать визиты поисковых роботов. Возможно, вы не захотите считать запросы, совершаемые из внутренней сети. Также может быть интересным считать только запросы авторизованных пользователей и т.д.

    Также важно понять, насколько критична точность подсчета, можно ли ошибиться на 1-2-3 единицы или нет. От этого может зависеть многое. Если важна точность, то можно пренебречь производительностью, или же наоборот, если важна производительность (например, скорость отдачи страницы), то можно незначительно пренебречь точностью.

    Хранение счетчиков

    Хранить счетчики можно тоже по-разному:
    • в базе данных в виде числового поля прямо в таблице сущности/страницы;
    • в базе данных в отдельной таблице, созданной специально для счетчиков, но также в виде простого числового поля;
    • сгруппировать разные счетчики, засериализовать их и также хранить в базе в BLOB или varchar-поле;
    • в какой-либо NoSQL базе, например, как Id -> count;
    • комбинация memcache + СУБД;
    • в файлах. Тут уж кто во что горазд, можно в одном файле в сериализованном виде, можно по файлу на сущность. В общем, можно много чего придумать, вплоть до реализации своей простой СУБД для хранения счетчиков.


    Пример из жизни

    Давайте рассмотрим конкретный пример из нашей практики. Сразу скажу, что мы используем MySQL.

    Задача: подсчет числа визитов страницы объявления раздела Купля-продажа проекта Авто Mail.Ru, без учета Web-ботов (Google, Яндекс, Поиск Mail.Ru). Также нужно считать, общее количество просмотров всех объявлений автосалона публикующего свои объявления о продаже на нашем портале Авто Mail.Ru.

    Важные моменты:
    • Точность подсчета важна, но в какой-то очень редкой форс-мажорной ситуации допустима потеря суммарно не более 200 визитов (это визиты всего за несколько минут в утреннее/дневное/вечернее время).
    • Нужна сортировка сущностей по числу визитов.
    • Обновление счетчика в базе в утренние/дневные/вечерние часы не реже одного раза в 30 минут. Это нужно для актуальности сортировок и адекватного отображения числа визитов в личном кабинете.


    Сначала попробовали реализовать «в лоб». Мы создали в таблице сущности поле views_count (аналогично в таблице автосалона) и обновляли его при каждом просмотре страницы объявления (делали UPDATE
    Всем удачи с подсчетами. Не изобретайте свои велосипеды без реальной необходимости.
    • +18
    • 20,6k
    • 9
    Mail.ru Group
    765,82
    Строим Интернет
    Поделиться публикацией

    Комментарии 9

      +3
      Любопытно, какая такая реальная необходимость заставила вас изобретать аналог Метрики и Google Analytics?
        0
        Нужно было: 1. не учитывать просмотры пользователем собственного объявления, 2. одновременно считать не только просмотры объявления, но и для автосалонов вести статистику по просмотрам их объявлений. Вот тут возникла основная сложность, т.к. при импорте объявлений от автосалонов, часто бывает, что одни объявления удаляются, а новые появляются. Как следствие, при удалении объявлений пропадает и статистика по ним, поэтому при увеличении счетчика просмотров объявлений мы инкрементим и счетчик просмотров у Автосалона. 3. по достижении определенного числа просмотров для автосалона производить некоторые триггерные действия (планировали производить биллинговые операции при достижении N просмотров).
        0
        Интересная тема. Но я бы сделал немного иначе.

        На сколько я понял, задача заключается в том, чтобы «быстро» записывать статистику. Подобную вещь я бы сделал асинхронной, чтобы не тормозила вывод страницы, а просто складывалась в очередь (например, Gearman). Создал бы воркер, который записывает в БД нужные данные (время, user-agent, url и т.п.) о каждом посещении (в качестве БД я бы выбрал PG, хотя и задумался бы над выбором NoSQL решения).

        Ещё можно распаралелить это дело. Для этого делаем master-master репликацию и поднимем на тех же серваках дополнительные воркеры для Gearman.

        Задержка записи логов стала большой? Количество задач стало увеличиваться? Добавляем воркеров. Не помогло? Добавляем новый сервак.
          0
          Да, такой механизм бесспорно более мощный, но и более сложный и трудозатратный в реализации. У нас на реализацию и внедрение ушло дня 2 с учетом небольшого нагрузочного теста. И потом еще пара часов на доработки и изменения бизнесс логики. А вообще для более сложной и мощной системы учту Ваш метод.
            +1
            Но это в случае, если надо обрабатывать ОЧЕНЬ большое количество запросов. Если справляется один сервак, то смысла городить подобную махину нет, согласен.

            А вообще, чтобы поднять такое, не нужно много времени.
            1) Установить и настроить Gearman (5 минут)
            2) Написать воркеры для обработки задачи практически на любом языке. Не 5 минут, но тоже быстро.
            3) Написать класс, который будет отсылать задачи гирмэну. Можно сохранить интерфейс класса, который записывает данные напрямую, сэкономим времени на интеграцию.
            4) Вот настройка репликации может занять не мало времени (по крайней мере у меня). Хотя если нам хватает мощностей одного сервака, то делать этого не стоит.

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

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

            Так что по времени тут за 2 дня можно очень легко уложиться, если, конечно, хорошо представлять себе что мы делаем ;)
          0
          В итоге таблицу счетчиков обновляем не 100 раз (размер окна), а в среднем 7 раз.

          Тогда уж стоило использовать Multiple Queries / Multiple Statement Execution.
            0
            На самом деле это сильно не изменило бы ситуацию. Все равно отработало бы внутри MySQL такое же число запросов. Экономия была бы разве что на сетевых операциях.
            +1
            В качестве окна можно использовать лог веб-сервера, это значительно уменьшит расходы на подсчет т.к. позволяет вообще не обращаться к бд при кэшировании страницы. Что касается таблицы в памяти, можно использовать буфферизированную запись лога (такая возможность есть например в nginx).
              0
              Если захотите опять поиграть с парсингом логов, может помочь моя утилитка, про которую я недавно написал пост. По крайней мере, при изменении формата урлов или логов не нужно будет лезть в исходники, все настраивается через конфигурацию. Правда, она заточена только под апач и совместимые логи.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое