TL;DR 我正在寻找一种按分钟存储、递增和检索事件计数范围的方法。
我正在寻找一种在 Redis 中创建递增时间序列的解决方案。我希望将计数存储到分钟。我的目标是能够查找时间范围并获取值。例如,如果特定键的事件每分钟发生 30 次。我想做一些类似 zrange 的事情并获得他们的关键值。我也希望使用像 zincrby 这样的东西来增加值(value)。我当然看过一个看起来非常合适的排序集,直到我意识到我只能对分数而不是值进行范围扫描。最佳解决方案是使用分钟数作为分数,然后使用排序集中的值作为该分钟的事件数。我遇到的问题是 zincrby 只会增加分数而不是值(value)。我无法找到一种方法来自动增加值。我还研究了一个 HashMap ,使用当前分钟作为键,事件计数作为值。我能够使用 hincrby 增加值,但问题是它不支持获取一系列键。
如有任何帮助,我们将不胜感激。
最佳答案
你知道,对了,一个问题已经有了答案。你已经说过 redis 解决问题的方法:
- 使用ZSET - 键作为时间,值作为计数器。
- 使用HSET - 键作为时间,值作为计数器。
- 使用string keys - 键名作为时间,值作为计数器。
为什么只有这种情况 - 因为只有这种结构( ZSET 、 HSET 和 string keys )具有增加值的原子方法。
实际上:
- 你应该对数据结构做出正确的选择。
- 解决数据选择问题。
第一个问题的答案是内存和性能之间的折衷。从你的问题来看,如果排序这样排序的集合不是最好的解决方案,你不需要任何类型 - 消耗大量内存和 ZINCRBY时间复杂度是 O(log(N)) 而不是 HINCRBY和 INCRBY是O(1)。所以我们应该在哈希和字符串键之间做出选择。请看question and answer关于 redis 中的正确内存优化 - 据此我认为您应该使用哈希作为解决方案的数据类型。
第二个问题对于任何类型的数据结构都是常见的,因为所有类型的数据结构都不包含按名称选择
功能或它们的类似物。我们可以使用 HMGET或 LUA 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/