【问题标题】:Page View Counter like on StackOverFlow像 StackOverFlow 上的页面查看计数器
【发布时间】:2008-10-29 14:06:48
【问题描述】:

在每个问题都有一个“浏览量”计数器的网站上,实现页面浏览计数器的最佳方法是什么?

考虑性能和可扩展性问题。

【问题讨论】:

    标签: asp.net


    【解决方案1】:

    我对 stackoverflow 视图计数器做了两个观察:

    • 标题中有一个link 元素,用于处理触发计数更新。对于这个问题,标记如下所示:
      <link href="/questions/246919/increment-view-count" type="text/css" rel="stylesheet" />
      我想你可以在没有实际查看页面的情况下点击该网址来更新观看次数,但我还没有尝试过。

    • 我有一个uservoice ticket,其中 Jeff 的响应表明视图不会连续两次从同一个 ip 递增。

    【讨论】:

    • 仅供以后阅读本文的人参考 - 我很确定他们自原始帖子以来已经改变了这一点。
    • 似乎是个好主意 - 将计数器保存在可缓存资源中,这样它只会在第一次“加载”资源时递增。为简单起见击败 cookie 和会话。
    • @tucuxi 你知道如何知道资源何时加载,何时不加载吗?谢谢
    • @oscar 如果它访问您的服务器,那么它正在被加载。有趣的是,页面的重复浏览将避免下载“未更改”的资源;这意味着在缓存清空之前不会有新请求到达您的服务器。
    • 这种方法效率不高,因为我可以清除我的缓存并再次点击计数器,再次清除我的缓存并再次点击它,无穷无尽..
    【解决方案2】:

    我优化的计数器是这样工作的:

    UPDATE page_views SET counter = counter + 1 WHERE page_id = x
    if (affected_rows == 0 ) {
       INSERT INTO page_views (page_id, counter) VALUES (x, 1)
    }
    

    这样您为第一个视图运行 2 个查询,其他视图只需要 1 个查询。

    【讨论】:

    • 这里的挑战之一是 a) 序列化的可能性或 b) 竞争条件 - 取决于您的事务隔离级别。
    • 是的,我们担心的一个问题可能是竞争条件。这应该异步完成吗?
    • @stephbu :对于您的 b) 来说,这更像是一个非关键的竞争条件,因为如果同时完成查询,+1 的增加不会改变...... +1 +1 或 +1 +1 总是等于 +2。
    • 您当然可以为每个新页面插入一行并将计数器设置为 0
    • @daok 就像我指出的那样,这取决于您的事务边界在哪里以及您对竞争条件的容忍度。
    【解决方案3】:

    一种有效的方法可能是: 将您的计数器存储在 Application 对象中,您可以将其定期保存到文件/数据库中并在应用程序关闭时保存。

    【讨论】:

      【解决方案4】:

      我不会在每次访问数据库时都调用数据库,而是使用缓存对象增加一个计数器,并根据您每天访问网站的次数,每 100 次访问将页面访问发送到数据库网站。这比每次点击更新数据库要快。

      或者另一种解决方案是分析 IIS 日志文件并通过 Windows 服务每 30 分钟更新一次命中。这就是我已经实现的,并且效果很好。

      【讨论】:

      • 我更喜欢您的解决方案。我来这里是为了寻找一种避免每次都碰到 DB 的解决方案。
      • 您有解决方案的示例或文档吗?
      【解决方案5】:

      你可以实现一个 IHttpHandler 来做到这一点。

      【讨论】:

        【解决方案6】:

        我很喜欢@Guillaume 的执行风格。我使用透明的 GIF 处理程序和内存队列来批量处理更改集,然后使用 global.asax 中创建的单独线程定期刷新这些更改集。

        处理程序实现 IHttpHandler,处理请求参数,例如页面id、语言等,更新队列,然后response.writes透明GIF。

        通过将持久更改移动到单独的线程而不是用户请求,您还可以更好地处理来自运行多个服务器等的潜在序列化问题。

        当然,您也可以付钱给其他人来做这项工作,例如带有透明 gif。

        【讨论】:

          【解决方案7】:

          对我来说,最好的方法是在问题表中设置一个字段并在访问问题时更新它

          UPDATE Questions SET views = views + 1 WHERE QuestionID = x
          

          应用程序对象:IMO 不可扩展,因为随着访问更多问题,可能会消耗大量内存。
          Page_views 表:不需要,你必须在之后做一个代价高昂的 join

          【讨论】:

          • @Eduardo 即使有 1000 万页也很实用-您仍然只在谈论最多 1000 万个整数-我想我只是打开 CLR 就烧掉了 50Mb ;) 内存很便宜-序列化不是.
          猜你喜欢
          • 1970-01-01
          • 2017-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多