用于存储非静态分布的数据库

时间:2012-09-05 16:39:23

标签: nosql redis distribution

我有许多分类分布。分类分布是指从一组k个事件中抽取事件的概率。我需要能够非常快速地访问事件的概率。

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

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

使用上面的redis方法,我可以每隔d分钟运行一次cron作业,迭代每个分布并减少zscore和规范化常量中的每个计数。然而,这似乎有点不对(我确信我的妈妈告诉我永远不要迭代KEYS *),所以我想知道是否还有其他人更全面地解决了这个问题?

1 个答案:

答案 0 :(得分:1)

我猜你觉得错的是:

  1. 每当cron作业运行时,都需要访问每个分发版,每个ZSET的每个成员以及规范化常量
  2. 无条件减量操作随着时间推移会偏向于每个cron周期多次发生的事件的分布方式
  3. 之前我没有做过这样的事情,但是如果你能够节省更多的存储空间,我会想到一个解决方案。

    我们的想法是定期存储时间戳快照队列。每个快照表示您的分配中该时间间隔内的事件计数。如果要使分发中的旧概率过期,可以从列表中弹出过期的快照并相应地减少ZSET。

    更具体地说,您需要:

    1. 记录间隔期间发生的事件[ t k - t k-1 )以及每次发生的次数发生 - 一组(事件,计数)对。这是您(目前)可能实时更新您目前所做的ZSET分数和归一化因素。
    2. 在每个刻度 t k 时,存储快照:
      1. 创建唯一键 S k 以表示 t k 处的快照 - 如UUID或类似
      2. 对于快照中的每个事件 E ,创建一个唯一的哈希键 q(E)。选择一个密钥编码,以便您恢复该事件的分发(ZSET)密钥和事件(成员)密钥。
      3. 使用事件键 q(E)和事件计数HSET | S k > E |用于存储事件数据。对快照中的所有事件重复此操作。
      4. RPUSH SNAPSHOTS <timestamp>: S k
    3. 在每个到期时刻度 t m ,过期旧快照:
      1. LPOP SNAPSHOTS列表,解码时间戳并验证是否过期。
      2. 如果没有过期,LPUSH它会重新进入SNAPSHOTS列表并完成,直到下一个到期时间为止。否则...
      3. 解码快照键 S k
      4. 使用HKEYS S k 的结果,解码每个事件键 q(E),得到相应的计数,然后按该数量减少适当的ZSET和归一化因子。
      5. 重复过期快照仍存在于SNAPSHOTS列表中。
    4. 所需的额外存储量取决于快照的长度和到期时间间隔以及每个快照时间间隔内发生的不同事件的数量。

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