【问题标题】:How to increment a redis sorted set's value如何增加 redis 排序集的值
【发布时间】:2016-01-28 16:04:44
【问题描述】:

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

我正在寻找在 redis 中创建递增时间序列的解决方案。我希望将计数存储到分钟。我的目标是能够查找时间范围并获取值。因此,例如,如果某个特定键的事件每分钟发生 30 次。我想做类似 zrange 的事情并获得他们的关键值。我也希望使用像zincrby这样的东西来增加价值。我当然看过一个看起来非常合适的排序集,直到我意识到我只能对分数而不是值进行范围扫描。最佳解决方案是使用分钟数作为分数,然后使用排序集中的值作为该分钟的事件数。我遇到的问题是 zincrby 只会增加分数而不是值。我无法找到一种以原子方式增加值的方法。我还研究了一个使用当前分钟作为键和事件计数作为值的哈希图。我能够使用 hincrby 增加值,但问题是它不支持获取一系列键。

任何帮助将不胜感激。

【问题讨论】:

    标签: java redis lettuce


    【解决方案1】:

    你知道,一个问题已经有了答案。你已经说过 redis 解决问题的方法:

    1. 使用ZSET - 键作为时间,值作为计数器。
    2. 使用HSET - 键作为时间,值作为计数器。
    3. 使用string keys - 键名作为时间,值作为计数器。

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

    事实上:

    1. 您应该正确选择数据结构。
    2. 解决数据选择问题。

    第一个问题的答案是内存和性能之间的折衷。从您的问题来看,如果对如此排序的集合进行排序不是最佳解决方案,则您不需要任何类型 - 消耗大量内存并且 ZINCRBY 时间复杂度是 O(log(N)) 而不是 @987654328 @ 和 INCRBYO(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中消耗的内存尽可能少。

    【讨论】:

    • 感谢您的信息!!我几乎得出了相同的结论,但是我没有考虑使用 hmget 来获取密钥列表。我在看 hscan 并且非常讨厌不得不这样做。我认为这是一个很好的解决方案!我还发现了一个 node 项目,它有一个非常相似的解决方案,我将模仿它。它使用哈希图来创建时间序列,取决于分钟/小时/秒等的粒度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多