Создание счетчика посещений с использованием кэша или области приложения
Я хотел бы создать счетчик посещений для моего приложения ColdFusion. Я не хочу, чтобы таблица посещений базы данных обновлялась при каждом обращении к странице. В идеале я хотел бы объединить попадания в область приложения или кэш в какой-либо структуре, а затем периодически их сохранять.
У меня есть идеи до сих пор.
Идея 1
- Создайте структуру приложения или кэша для хранения пары ключ-значение pageId и pageHits.
- На каждом обращении к странице проверяйте наличие файла cookie для идентификатора страницы / IP-адреса.
- а. Если он существует, ничего не делать.
- б. Если это не так, установите его и обновите структуру попаданий в приложении или кеше.
Проблема: я не знаю, как получать данные структуры в базу данных периодически / по истечении определенного времени. Запланированное событие?
Идея 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]));
Однако, если я снова зайду на страницу, я не буду засчитан?