使用缓存或应用程序范围创建命中计数器

发布于 2024-11-11 14:51:05 字数 696 浏览 2 评论 0原文

我想为我的 ColdFusion 应用程序创建一个点击计数器。我不希望在每个页面点击时更新数据库点击表。理想情况下,我想聚合应用程序范围内的命中或某种类型的结构中的缓存,然后间歇性地保存它们。

到目前为止我有想法:

想法1

  1. 创建一个应用程序或缓存结构来存储 pageId 和 pageHits 键值对。
  2. 在每个页面点击时,检查 pageId/ip 地址 cookie 是否存在。
  3. 一个。如果存在,则不执行任何操作。
  4. b.如果没有,请设置它并更新应用程序或缓存中的命中结构。

问题:我不知道如何间歇性/经过一定时间后将结构数据存入数据库。预定的活动?

想法 2

无 cookie;将 pageId/ip 地址保存在自己的缓存/应用程序结构中。

问题我不确定如何构建数据结构/数组来存储信息。数组循环和结构查找似乎很复杂。我仍然遇到与想法一相同的问题。

有什么建议、想法、批评吗?特别是,我需要一些帮助来确定想法 2 的数据结构。我对性能比数据完整性更感兴趣,并且对仅 CF9 的解决方案感到满意。 我应该补充一点,我希望将数据非规范化到每个页面 ID 的页面点击列中。我不需要标准化的数据表。

I would like to create a hit counter for my ColdFusion app. I don't want the database hits table to be updated on each page hit. Ideally, I would like to aggregate the hits in the app scope, or the cache in some type of struct, then save them intermittently.

I have to ideas so far:.

Idea 1

  1. Create an app or cache struct to store pageId and pageHits key value pair.
  2. On each page hit, check for the existence of pageId/ip address cookie.
  3. a. If it exists, do nothing.
  4. b. If it does not, set it and update the hits struct in the app or cache.

Problem: I don't know how to get the struct data into the database intermittently/after a certain time has elapsed. Scheduled event?

Idea 2

No cookies; save pageId/ip address in their own cache/app struct.

Problem I'm not sure how to structure the data structs/arrays to store the info. Seems complicated with array loops and struct finds. And I still have the same problem as idea one.

Any advice, ideas, criticism? In particular, I need some help figuring out the data structures for idea 2. I'm more interested in performance than data integrity and happy with CF9 only solution. I should add I'm looking to denormalize data into a page hits column for every page id. I don't need normalized data tables.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眉目亦如画i 2024-11-18 14:51:05

尝试以您所描述的方式捕获此数据会引入缓存过期的扩展问题,以避免 OOM 或当您最终想要持久保存到数据库时条目数量增加时的长迭代时间。您想要聚合的信息已在 Web 服务器日志中捕获。解析这些是一项简单的活动,您只需要编写一个算法来了解这些翻转的方式和时间。

使用 log = fileRead('log.txt', 'read') 并通过 定期迭代 line fileReadLine(log) ;。对于每个批次,您可以按照已经描述的方式,然后使用任何 基于 IP 地址的 INSERT/UPDATE 数据库方法(通常使用 MERGE 关键字,但 MySQL 不同)(如果这就是您所追求的)。如果它是一个非常高流量的站点,请考虑更改 的数据类型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()),它跟踪它所在的线路。然后,当 再次点击此代码时,它会使用现有引用(如果存在)并从那里向前迭代。锁确保只有一个线程执行该算法 - 因此您无需担心时间限制,只要让它继续运行即可。

Trying to capture this data in the ways you've describe introduces scaling problems with cache expiration to avoid OOM or long iteration times as the number of entries grows when you ultimately want to persist to a database. The information you want to aggregate is already captured in web server logs. Parsing these is a straightforward activity, you just need to write an algorithm that's aware of how and when these rollover.

Use log = fileRead('log.txt', 'read') and iterate over line fileReadLine(log) on a periodic basis via <cfschedule/>. For each batch you can in the fashion you've already described and then use whatever database approach for INSERT/UPDATE (usually uses the MERGE keyword, but MySQL is different) based on IP address if that's what you're after. If it's a very high traffic site, consider altering the data type of the IP address column to an integer datatype to speed index lookups.

Update

Use the following code to setup a file object reference:

<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>

Doing this sets up the reference once (i.e. fileOpen()), which keeps track of what line it's on. Then when <cfschedule/> hits this code again it uses the existing reference if present and iterates forward from there. The lock ensures only one thread executes the algorithm - so you don't need to to worry about a time constraint just let it keep on going as long as it needs to.

夜深人未静 2024-11-18 14:51:05

想法1:是的,是你的朋友

想法2:保存pageId/ip地址?我想这最好使用Java中的Set,但是如果你给它分配一个空值,struct也可以工作...

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

但是,如果我再次访问该页面tmr,我将不会被计算在内?

Idea 1: yes, <cfschedule> is your friend

Idea 2: save pageId/ip address? I guess this is better to use Set from Java, but struct would work too if you assign it an empty value...

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

However, if I visit the page again tmr, I won't be counted?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文