10

What's the best way to increment a medium size sorted set in REDIS? (Preferably with java driver JEDIS) Set has about 100-200K records in it. I want to increment their score by a given double number.

before

1 a
2 b
3 c

after (increment by 1)

2 a
3 b
4 c

The only possible solution i came up with is:

  1. Fetch all sorted set (say A) contents over the network. (REDIS -> application).
  2. Create a pipeline, increment them in the same setA with ZADD or ZINCRBY in a loop
  3. Then execute the pipeline.

Is there another/better way to do it?

UPDATE

Here's how to do a for loop to increment all sorted set members using EVAL and Lua in REDIS.

local members = redis.call('zrange',KEYS[1],0,-1)
for i, member in ipairs(members) do
    redis.call('zincrby',KEYS[1],inc,member)
end

Save this into a string and run eval using your driver (java in this case). Execution returns nothing.

using Jedis

// script is the script string
// 1 is the number of keys- keep it this way for this script
// myzset is the name of your sorted set
// 1.5 is the increment, you can use +/- values to inc/dec.
jedis.eval(script, 1, "myzset", "1.5");
Onur Günduru
  • 451
  • 4
  • 14

1 Answers1

3

Communicating between the client and redis may take a lot of time. To avoid that, you can take a "SET-type" copy of the sorted set. For instance, say you have a sorted set "key1":

1 a
2 b
3 c

And you have a set "key2":

a, b, c

Than you can implement the increment easily:

def increase_sorted_set(increment = 1)
  redis.ZINTERSTORE("key1", 2, "key1", "key2", "WEIGHTS", "1", increment)
end

Redis will give each member of the (non-sorted) set key2 a default score of 1.

For example:

redis 127.0.0.1:6379> ZADD key1 1 a 2 b 3 c
(integer) 3
redis 127.0.0.1:6379> SADD key2 a b c
(integer) 3
redis 127.0.0.1:6379> ZINTERSTORE key1 2 key1 key2 WEIGHTS 1 7
(integer) 3
redis 127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "a"
2) "8"
3) "b"
4) "9"
5) "c"
6) "10"
luin
  • 2,077
  • 2
  • 20
  • 23
  • I didn't know ZINTERSTORE could take SET as an argument. How can i create a "SET-type" copy of the sorted set? – Onur Günduru Feb 21 '13 at 13:46
  • You have to fetch all the elements of key1 over the network(ZRANGE key1 0 -1) and use SADD to add the elements to the key2, or use scripting(http://redis.io/commands/eval) to do it on the server side. After that, when you want to add a new element to the key1, just add the element to the key2 too. – luin Feb 21 '13 at 14:21
  • I'll check EVAL. Duplicating the set might be a quick fix. However my resources are limited and i have lots of similar sets. Besides i need to duplicate code for remove operations as well as add operations. Thanks, will accept this until a future release :) Still hoping for a better way – Onur Günduru Feb 21 '13 at 15:19
  • @luin one enhancement, instead of using zinterstore, we can use zunionstore. this way, we won't have to create another sorted set with the exact number of elements. – Mukul Bansal Feb 23 '22 at 20:09