Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REDIS/jedis update scores of all members in a sorted set

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");
like image 718
Onur Günduru Avatar asked Feb 21 '13 12:02

Onur Günduru


1 Answers

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"
like image 190
luin Avatar answered Sep 20 '22 12:09

luin