2015-10-28 53 views
6

TL; DR我正在寻找一种方法来存储,增量和检索事件计数范围的分钟。如何增加redis排序集的值

我正在寻找一种解决方案来在redis中创建增量时间序列。我期待着将计数存储到一分钟。我的目标是能够查找时间范围并获取值。因此,如果每分钟30次发生特定键的事件。我想要做一些像zrange一样的东西并获得它们的关键值。我也希望能够使用像锌这样的东西来增加价值。我当然看过一个看似完美的排序集,直到我意识到我只能对得分而不是价值进行范围扫描。最佳解决方案是使用分钟数作为分数,然后使用排序集中的值作为该分钟的事件数量。我遇到的问题是锌银只会增加分数而不是价值。我无法找到一种方法来自动增加值。我还使用当前分钟作为键值和事件计数来查看哈希映射。我能够使用hincrby来增加值,但问题是它不支持获取一系列键。

任何帮助,将不胜感激。

回答

4

你知道,对一个问题已经有一个答案。你已经说,关于Redis的方式来解决问题:

  1. 使用ZSET - 关键的时间和值计数器。
  2. 使用HSET - 作为计数器的时间和价值的关键。
  3. 使用string keys - 作为计数器的时间和价值的关键名称。

为什么只有这种情况下 - becouse仅此结构(ZSETHSETstring keys)的原子的方法来增加价值。

所以actualy:

  1. 您应该对数据结构的最佳的选择。
  2. 解决数据选择问题。

第一个问题的答案是内存和性能之间的妥协。从你的问题你不需要任何类型,如果排序如此排序的集合不是一个最佳的解决方案 - 消耗大量的内存和时间复杂度为O(log(N))HINCRBYINCRBYO(1)。所以我们应该选择哈希和字符串键。请看question and answer关于redis中正确的内存优化 - 根据这个我认为你应该使用散列作为你的解决方案的数据类型。

第二个问题对于任何类型的数据结构都是通用的,因为它们的所有类型都不包含select by name功能或它们的类似物。我们可以使用HMGETLUA scripting来解决这个问题。在任何情况下,这个解决方案的时间复杂度将会是O(n)

下面是样品与Jedis(我真的不是Java程序员,遗憾的可能的错误):

int fromMinute = 1; 
int toMinute = 10; 

List<String> list = new ArrayList<String>(); 
for(int i = fromMinute ; i < toMinute ; i++) { 
    list.add(i.toString()); 
} 

Jedis jedis = new Jedis("localhost"); 
List<String> values = jedis.hmget("your_set_name", list); 

该解决方案是原子的,快速,具有时间复杂度为O(n)和消耗内存在redis中尽可能少。

+0

感谢您的信息!我几乎得出了相同的结论,但我没有考虑hmget获取密钥列表。我正在看hscan,非常讨厌这样做。我认为这是一个很好的解决方案!我还找到了一个节点项目,它有一个非常类似的解决方案,我将模仿。它使用hashmaps来创建时间序列,依赖于分钟/小时/秒的粒度等。 –

+1

忘记授予节点库http://blog.apiaxle.com/post/storing-near-realtime-stats-in- Redis的/ –