Создание счетчика посещений с использованием кэша или области приложения

Я хотел бы создать счетчик посещений для моего приложения ColdFusion. Я не хочу, чтобы таблица посещений базы данных обновлялась при каждом обращении к странице. В идеале я хотел бы объединить попадания в область приложения или кэш в какой-либо структуре, а затем периодически их сохранять.

У меня есть идеи до сих пор.

Идея 1

  1. Создайте структуру приложения или кэша для хранения пары ключ-значение pageId и pageHits.
  2. На каждом обращении к странице проверяйте наличие файла cookie для идентификатора страницы / IP-адреса.
  3. а. Если он существует, ничего не делать.
  4. б. Если это не так, установите его и обновите структуру попаданий в приложении или кеше.

Проблема: я не знаю, как получать данные структуры в базу данных периодически / по истечении определенного времени. Запланированное событие?

Идея 2

Нет печенья; сохранить pageId / IP-адрес в своей собственной структуре кэша / приложения.

Проблема Я не уверен, как структурировать структуры данных / массивы для хранения информации. Кажется сложным с циклами массива и структурными находками. И у меня все та же проблема, что и у первой идеи.

Любой совет, идеи, критика? В частности, мне нужна помощь в выяснении структур данных для идеи 2. Меня больше интересует производительность, чем целостность данных, и я доволен решением только с CF9. Я должен добавить, что я ищу денормализацию данных в столбец посещений для каждого идентификатора страницы. Мне не нужны нормализованные таблицы данных.

2 ответа

Решение

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

использование log = fileRead('log.txt', 'read') и перебрать line fileReadLine(log) на периодической основе через <cfschedule/>, Для каждого пакета вы можете, как вы уже описали, и затем использовать любой подход к базе данных для INSERT/UPDATE (обычно используется ключевое слово MERGE, но MySQL отличается) на основе IP-адреса, если это то, что вам нужно. Если это сайт с очень высоким трафиком, рассмотрите возможность изменения типа данных столбца IP-адреса на целочисленный тип данных для ускорения поиска по индексу.

Обновить

Используйте следующий код для установки ссылки на объект файла:

<cflock name="logparser" type="exclusive" timeout="1" throwontimeout="false">
    <cfif NOT structKeyExists(application, "logFile")>
        <cfset application.logFile =
            fileOpen('/path/to/log.txt', 'read')>
    </cfif>
    <cfloop condition="NOT FileisEOF(application.logFile)">
        <!--- replace with an appropriate algorithm --->
        <cfoutput>
            #fileReadLine(application.logFile)#
            <br />
        </cfoutput>
    </cfloop>
</cflock>

Делая это устанавливает ссылку один раз (т.е. fileOpen()), который отслеживает, на какой линии он находится. Тогда, когда <cfschedule/> снова нажимает на этот код, использует существующую ссылку, если она есть, и выполняет итерацию вперед оттуда. Блокировка гарантирует, что только один поток выполняет алгоритм - так что вам не нужно беспокоиться о временном ограничении, просто дайте ему продолжаться столько времени, сколько потребуется.

Идея 1: да, <cfschedule> твой друг

Идея 2: сохранить идентификатор страницы / IP-адрес? Я полагаю, что лучше использовать Set из Java, но struct тоже сработает, если вы назначите ему пустое значение...

pageIDs["1"]["192.0.0.1"] = "";
hitsOfPage1 = structCount(pageIDs[1]));

Однако, если я снова зайду на страницу, я не буду засчитан?

Другие вопросы по тегам