一段时间内实时最常见/最重要的元素

时间:2017-08-29 21:39:49

标签: algorithm nginx go data-structures

我有一个用户生成的字符串以不确定的速率进入,其中一些是重复数据,我想实时保留前20个最常见重复项的数量,在给定的恒定时间段内(例如,在过去一小时内),在Go。

唯一字符串的数量不受任何限制,因此,为避免DoS,数据结构可能必须具有大多数元素的定义大小(例如,前10k元素和/或1MB整体大小),如果它们还没有任何重复项,则删除最近插入的元素(但不要删除任何新传入的元素!)。

我的理解是,这正是ngx_http_limit_req_module.c implemented的确切方式,documentation中将此方法称为“漏桶”,但wikipedia页面似乎表明它是从队列中删除的新数据,而不是旧数据,因此,不确定该概念是否适用。

无论如何,我试图在Golang中寻找一个“漏桶”实现,到目前为止我找到的最流行的结果是uber-go/ratelimit,其API似乎根本不符合我的问题陈述 - 它只是实现一些实际的速率限制队列,而不是实时的最后一次Y计数的前X。

任何人都可以建议我正在寻找的正确名称,以及实现这一目标的最佳方式,最好是在Go?

1 个答案:

答案 0 :(得分:-1)

这是两个问题。

  1. 跟踪您选择跟踪的名称。
  2. 注意不在列表中的趋势名称,以便跟踪。
  3. 对于第一个问题,我建议按名称,每分钟跟踪,有多少。完成后,将它们添加到运行总计中,然后添加到一个事物队列中,以便在一小时内减去。这为每个名称提供了60个小对象,并且在运行的基础上,您将保持哈希值。

    第二个问题更具挑战性。为此我会使用概率方法。我们的想法是每个名称都使用唯一ID进行哈希处理,并且您只保留一分钟内看到的千个最小哈希值(以及相关名称)。 (我将在一分钟内给出一个算法。)你的哈希值应该在名称中独立分布在2 ^ 64之间,因此常用名称最终将显示在此列表中。当他们这样做时,你开始计算它们! (你将失去前几个,但是你可以通过更多的工作来估计你错过了多少。虽然这种优化可能比它的价值更多。)

    现在我们如何保持千个最小的哈希值?您使用优先级队列,它通常使用实现,以创建可更新的数据结构,从而可以轻松获取最大的哈希值。所以你运行以下伪代码。

    create your priority queue of (hash, name)
    for each name:
       hash hash of name and unique new id
       entry = (hash, name)
       if queue size < 1000:
           insert entry
       else if hash is smaller than the current max in the queue
          insert entry
          remove the largest entry