【问题标题】:Creating a hit counter using the cache or application scope使用缓存或应用程序范围创建命中计数器
【发布时间】:2011-05-31 17:10:51
【问题描述】:

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

到目前为止我有想法:。

想法 1

  1. 创建应用或缓存结构来存储 pageId 和 pageHits 键值对。
  2. 在每个页面点击时,检查是否存在 pageId/ip 地址 cookie。
  3. 一个。如果存在,则什么也不做。
  4. 乙。如果没有,请设置它并更新应用或缓存中的 hits 结构。

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

想法 2

没有cookies;将 pageId/ip 地址保存在自己的缓存/应用结构中。

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

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

【问题讨论】:

    标签: architecture coldfusion coldfusion-9 hit


    【解决方案1】:

    尝试以您描述的方式捕获此数据会引入缓存过期的扩展问题,以避免 OOM 或在您最终希望持久保存到数据库时随着条目数量的增长而导致较长的迭代时间。您要汇总的信息已在 Web 服务器日志中捕获。解析这些是一个简单的活动,您只需要编写一个知道这些翻转的方式和时间的算法。

    使用log = fileRead('log.txt', 'read') 并通过<cfschedule/> 定期迭代line fileReadLine(log)。对于每个批次,您可以按照您已经描述的方式,然后使用基于 IP 地址的任何database approach for INSERT/UPDATE (usually uses the MERGE keyword, but MySQL is different),如果这是您所追求的。如果它是一个非常高流量的网站,请考虑更改 IP address column to an integer datatype to speed index lookups. 的数据类型

    更新

    使用以下代码设置文件对象引用:

    <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()),它会跟踪它所在的行。然后当&lt;cfschedule/&gt; 再次点击此代码时,它会使用现有引用(如果存在)并从那里向前迭代。锁确保只有一个线程执行算法——所以你不需要担心时间限制,只要让它继续运行就可以了。

    【讨论】:

    • 感谢您解决这个问题。我忘了提一件事:由于页面本身保存在数据库中,我会将命中数据非规范化为单个页面命中列):如果我每 60 秒运行一次此服务,并且日志文件变得非常大,我该如何阅读只有 60 秒的日志行?如果我的日志文件有 10,000 行,但我只需要在最后 60 秒内创建的行……这种方法可行吗?我不是在寻找标准化数据。
    • @Mohamad:查看我的更新。简短的回答是不要担心时间限制,使用 &lt;cflock/&gt;fileOpen() 参考代替。
    • 我还没有开始实施这个,但我会在这个周末试一试。不过,今天早上我在想,我突然想到:您将如何跟踪独特的热门歌曲!如果每个访问者在 3 小时后都算作一次唯一点击,那么算法必须解析每一行并确定最后 x 时间是否存在重复值。这可行吗?
    • @Mohamad:我可能会将每个命中放入包含 IP 地址、URL 和时间戳的数据库表中。然后在这些行上运行 DISTINCT 并使用 WHERE 子句来限制时间段。这应该会给你你想要的信息。
    【解决方案2】:

    想法 1:是的,&lt;cfschedule&gt; 是你的朋友

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

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

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

    【讨论】:

    • 为什么我不做hits[1].page = { pageId = 1, ipAddress = 192.0.0.0 } 之类的事情呢?在这种情况下,我很难可视化数据的结构!此外,在 cookie 场景中,我可以让它在几个小时后过期。在第二个想法中,我还不知道它是如何工作的。
    • 因为你想要的命中计数器最常见的答案是...... pageID = X 有多少命中。你需要一个支持它的数据结构。您的目标数据结构无法轻松回答“where pageId = 1”部分。
    猜你喜欢
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 2014-12-31
    • 2015-02-03
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多