我有很多分类分布。类别分布是一种描述从一组k个事件中得出一个事件的概率的情况。我需要能够快速访问事件的可能性。

存储分类分布的一种方法是在Redis中使用排序集。每个键索引一个单独的分布,排序集中的每个成员是一个特定事件,每个分数是您看到该事件的次数。对于每个键(分布),您还将在该分布中存储每个事件的计数总和,因此您可以正确地进行规范化。

我想问的问题是:如果概率随时间变化,什么是存储此数据的好方法?我本质上希望能够忘记旧的观察-即以一定的间隔减少每个键的得分和归一化常数。

使用上面的redis方法,我可以每d分钟运行一次cron作业,遍历每个分布并递减zscore和规范化常数中的每个计数。但是,这似乎有点不对(我确定妈妈已经告诉我不要迭代KEYS *),所以我想知道是否还有其他人能够更全面地解决此问题?

最佳答案

我猜测您感到不对的是以下几种组合:

  • 每当cron作业运行
  • 时,就需要访问每个发行版,每个ZSET的每个成员以及规范化常数
  • 无条件减量操作随着时间的推移将偏向于分布,以支持每个cron周期多次发生的事件的方式

  • 我以前没有做过这样的事情,但是如果您能够腾出更多的存储空间,就会想到一个解决方案。

    想法是定期存储带时间戳的快照队列。每个快照代表该时间间隔内分发中的事件计数。如果要使分发中的旧概率失效,则将失效的快照从列表中弹出,并相应地减少ZSET。

    更具体地说,您需要:
  • 跟踪内存在[tk-tk-1)间隔内发生的事件以及每次发生的次数-一组(事件,计数)对。这是对(当前)实时更新ZSET分数和归一化因子的补充。
  • 在每个tk时刻,存储快照:
  • 创建一个唯一的密钥Sk来表示tk的快照-例如UUID或类似的
  • 对于快照中的每个事件E,创建唯一的哈希键q(E)。选择一种密钥编码,该编码将允许您恢复该事件的分发(ZSET)密钥和事件(成员)密钥。
  • 用事件键q(E)和事件计数HSET E |调用| Sk以存储事件数据。重复快照中的所有事件。
  • RPUSH SNAPSHOTS <timestamp>: Sk
  • 在每个到期时间tm,使旧快照到期:
  • LPOP SNAPSHOTS列表,解码时间戳并验证是否过期。
  • 如果未过期,请对其进行LPUSH编码回到SNAPSHOTS列表中,直到下一个到期滴答为止。否则...
  • 解码快照密钥Sk
  • 使用HKEYS Sk的结果,对每个事件密钥q(E)进行解码,获取相应的计数,然后将相应的ZSET和归一化因子减少该数量。
  • 在SNAPSHOTS列表中仍然存在过期的快照时重复。

  • 所需的额外存储量将取决于快照的长度和到期间隔以及每个快照间隔内发生的不同事件的数量。

    在最坏的情况下,每个分发和事件都将在每个快照中表示,因此这对于错误因子1毫无帮助。乐观地,将在任何快照中代表适当比例的分布和/或事件,并且到期过程的效率将得到提高。但这即使在最坏的情况下也可以解决错误因素2,因为最近发生的事件不会在每次到期cron作业运行时无条件地在您的分布中减少。

    关于nosql - 用于存储非平稳分布的数据库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12286022/

    10-15 22:28