Chris Hinshaw
Chris Hinshaw

Reputation: 7255

How to increment a redis sorted set's value

TL;DR I am looking for a way to store, increment and retrieve ranges of event counts by minute.

I am looking for a solution to creating an incrementing timeseries in redis. I am looking to store counts to the minute. My goal is to be able to look up a time range and get the values. So for instnace if an event occurred for a specific key 30 times a minute. I would want to do something like zrange and get their key values. I also am hoping to use something like zincrby to increment the value. I have of course looked at a sorted set which would have seemed like a perfect fit until I realized that I can only do a range scan on the score and not the value. The optimal solution would be to use the number of minutes as the score and then use the value in the sorted set as the number of events for that minute. The problem I ran into is the zincrby only increments the score and not the value. I was unable to find a way to increment the value atomically. I also looked into a hashmap using the current minute as the key and event count as the value. I was able to increment the value using hincrby but the problem is that it doesn't support fetching a range of keys.

Any help would be appreciated.

Upvotes: 7

Views: 4073

Answers (1)

Nick Bondarenko
Nick Bondarenko

Reputation: 6351

You know, right a question already has an answer. And you already says about redis way to solve your problem:

  1. Use ZSET - key as time and value as counter.
  2. Use HSET - key as time and value as counter.
  3. Use string keys - key name as time and value as counter.

Why only this cases - becouse of only this structures (ZSET, HSET and string keys) has atomic methods to increment values.

So actualy:

  1. You should make right choise about data structure.
  2. Resolve the issue with the data selection.

The first question answer is compromise between memory and perfomance. From your question you do not need to have any types if sorting so sorted sets is not a best solution - consume lot of memory and ZINCRBY time complexity is O(log(N)) rather HINCRBY and INCRBY is O(1). So we should choose betweeh hashes and string keys. Please look at question and answer about right memory optimization in redis - according this i think you should use hashes as a data type for your solution.

The second question is common for any types of data structures becouse of all types of them do not contains select by name features or they analogs. And we may use HMGET or LUA scripting to solve this problem. In any case this solution would have time complexity O(n).

Here is sample with Jedis (i`m not an Java programmer, sorry for possible errors):

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);

This solution is atomic, fast, has time complexity O(n) and consume memory as little as possible in redis.

Upvotes: 3

Related Questions