【问题标题】:High performance impression tracking高性能展示跟踪
【发布时间】:2012-07-13 19:18:54
【问题描述】:

基本上,我想跟踪的部分指标是某些对象在我们的营销平台上获得的展示量。 如果您想象我们展示了很多对象,我们希望在每次提供对象时进行跟踪。

每个对象都通过单个网关/接口返回给客户端。因此,如果您设想一个请求进入了具有某些搜索条件的页面,然后该搜索请求被代理到我们的 Solr 索引。

然后我们得到 10 个结果。

这 10 个结果中的每一个都应被视为一次展示。

我正在努力寻找一个令人难以置信的快速和准确的实现。

关于如何做到这一点的任何建议?你可以投入任意数量的技术。我们目前使用的是 Gearman、PHP、Ruby、Solr、Redis、Mysql、APC 和 Memcache。

最终所有的印象最终都应该被持久化到 mysql 中,我每小时都可以这样做。但我不确定如何在不影响实际搜索请求的加载时间的情况下快速将展示次数存储在内存中。

想法(我刚刚添加了选项 4 和 5)

  1. 将结果返回给客户端后,客户端随后会在我们的平台上请求一个 base64 编码的 URI,其中包含已提供服务的所有对象的 ID。然后将此对象传递给 gearman,然后将计数保存到 redis。每小时一次,redis 被刷新一次,并且 mysql 中每个对象的计数都会增加。

  2. 从 Solr 返回结果后,循环并直接保存到 Redis。 (尚未对此进行速度基准测试)。每小时重复一次刷新到mysql。

  3. 从 Solr 返回项目后,将单个作业中的所有 ID 发送给 gearman,然后将其提交给 Redis..

  4. 新想法 由于返回的项目数最多约为 20,因此我可以设置一个 X-Application-Objects 标头,其中包含返回的 ID 的 base64 标头。然后,这些 ID(在标头中)可以被 nginx 剥离,并使用自定义 LUA nginx 模块,我可以将 ID 从 nginx 直接写入 Redis。不过,这可能有点矫枉过正。这样做的好处是我可以告诉 nginx 在写入 redis 时立即返回响应对象。

  5. 新想法 使用fastcgi_finish_request() 将请求刷新回 nginx,然后将结果插入 Redis。

  6. 还有其他建议吗?

编辑回答问题:

这些数据的可靠性并不重要。只要是最好的猜测。我不希望看到 30% 的展示次数下降。但我会允许 10% -/+ 的精度。

【问题讨论】:

  • 数据有多重要?如果你失去了,比如说,100 次展示,那是不是很糟糕?如果你输了1,那是不是很糟糕?如果在这方面有一定的灵活性,那么也许有某种缓存的地图,它有一个活跃的线程来持久化它。
  • 另外,这个数据的检索需求是什么?您是否需要能够立即查询并获得及时的结果?或者您可以将印象转储到某种日志中,然后在批处理作业中每晚进行处理?
  • Marvo,数据不重要。它用于向对象的所有者提供统计信息。向他们提供详细信息,例如点击率等。丢失一些数据是可以的。我希望经常丢失一些(例如当我重新启动服务器并且过去几个小时的结果没有被刷新回 mysql 时)。我打算从 Redis 获取结果并推送到 mysql。
  • 我们在谈论什么样的数字?有多少对象和展示次数,以及您是否有任何增长估算。
  • 您好,我也在尝试跟踪展示次数。您是否担心在结果中也包含机器人流量?这可能会使您的准确度指针超过您的允许阈值。如果是这样,您想出什么方法来过滤此流量?我很想知道:)

标签: php solr redis gearman


【解决方案1】:

我认为您的两个最佳选择是:

  1. 使用增量命令我 redis 在您拉动 dis 时递增计数器。使用 Id 作为键并在 Redis 中递增。 Redis 每秒可以轻松处理数十万个增量,因此速度应该足够快,不会对客户端产生任何明显的影响。如果 PHP 语言绑定支持它,您甚至可以对每个请求进行管道传输。我认为是的。

  2. 使用 redis 作为普通缓存。在此选项中,您只需使用 Redis 列表并执行包含由例如分隔的 ID 的字符串的 rpush。一个逗号。您可以使用一天中的小时作为键。然后,您可以有一个单独的进程通过抓取前一个小时并按您想要的方式将其按摩到 MySQL 中来将其拉出。我希望您在密钥上设置一个过期时间,您可以在一段时间后将它们清除,或者只是通过后处理过程删除密钥。

如果您的 redis 流量非常高,或者只是想卸载它并获得备份作为奖励,您也可以使用读取从属设备导出到 MySQL。如果这样做,您可以将主 redis 实例设置为不刷新到磁盘,从而提高写入性能。

有关更广泛地使用 redis 功能进行此类跟踪的一些其他选项,请参阅this answer 您还可以避免 MySQL 部分并从 redis 中提取数据,从而使整个系统更简单。

【讨论】:

    【解决方案2】:

    我会执行 #2 之类的操作,然后将数据交给您可以更新 Redis 计数器的最快队列。我对 Gearman 不是很熟悉,但我敢打赌这很慢。如果您的 Redis 客户端支持异步写入,我会使用它,或者将它放在单独线程的队列中。您不想在等待更新计数器时减慢响应速度。

    【讨论】:

    • 您也可以以适合加载到 MySQL 的形式异步记录到文件,因为这是您的最终目标。比如说,写入一个选项卡文件,当日志文件旋转时,运行LOAD DATA INFILE 以推送到数据库中。
    猜你喜欢
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多