TL; DR我正在寻找一种按分钟存储,递增和检索事件计数范围的方法。

我正在寻找在Redis中创建递增时间序列的解决方案。我希望将计数存储到分钟。我的目标是能够查找时间范围并获取值。因此对于实例而言,如果某个事件每分钟发生30次特定键,则该事件为例。我想做类似zrange的操作并获取其键值。我也希望使用诸如zincrby之类的值来增加该值。当然,我看了一个看起来很合适的有序集合,直到我意识到我只能对分数而不是数值进行范围扫描。最佳解决方案是将分钟数用作得分,然后将排序集中的值用作该分钟的事件数。我遇到的问题是zincrby仅增加得分而不是增加值。我无法找到一种自动增加值的方法。我还研究了使用当前分钟作为键并将事件计数作为值的哈希图。我可以使用hincrby来增加值,但问题是它不支持获取一系列键。

任何帮助,将不胜感激。

最佳答案

您知道,对一个问题已经有了答案。您已经说过关于Redis解决问题的方法:

  • 使用ZSET-键作为时间,值作为计数器。
  • 使用HSET-键作为时间,值作为计数器。
  • 使用string keys-键名作为时间,值作为计数器。

  • 为什么只有这种情况-因为仅这种结构(ZSETHSETstring keys)具有原子方法来增加值。

    所以实际上:
  • 您应该正确选择数据结构。
  • 解决数据选择问题。

  • 第一个问题的答案是内存与性能之间的折衷。从您的问题出发,如果排序排序的集合不是最佳解决方案,则不需要任何类型-消耗大量内存并且ZINCRBY时间复杂度为 O(log(N))而不是HINCRBYINCRBY O(1) 。因此,我们应该选择betweeh散列和字符串键。请查看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中消耗的内存尽可能少。

    关于java - 如何增加Redis排序集的值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33398564/

    10-14 13:49