5

Due to performance, I need to minimize the number of hops to Redis. I am calling HMSET multiple times from C++ code and I am investigating if it is possible to change this by using Lua script and set multiple Redis hash keys with one call to Redis:

HMSET myhash1 field1 "Hello" field2 "World"
HMSET myhash2 field1 "Hello" field2 "World"
HMSET myhash3 field1 "Hello" field2 "World"
...
HMSET myhashN field1 "Hello" field2 "World"

How can I pass to the script multiple hash keys and multiple fields/values?


UPDATE Based on Itamar Haber comment, I figured out that my problem was the comma with a space missing between the KEYS and ARGV values -

I ended up to the following script:

local k = 1 
for i=1,  #KEYS do
    if redis.call('hmset', KEYS[i], ARGV[k], ARGV[k+1], ARGV[k+2], ARGV[k+3]) == 1 then
        return 1
    end 
    k = k + 4 
end                                                                                                                                                                                             
return 0

redis-cli --eval /var/tmp/script.lua myhash1 myhash2 , field1 "Hello" field2 "World" field1 "Hello" field2 "World"

I am not sure if it can be optimized further to avoid repeating the field names or passing arbitrary number of fields/values for each key.

Sled
  • 18,541
  • 27
  • 119
  • 168
georgeliatsos
  • 1,168
  • 3
  • 15
  • 34

2 Answers2

2

To minimize the hops you can use pipelining instead - simpler and has the desired effect.

A script can also minimize the hops. Use the KEYS array to pass you Hash key names to the script and the ARGV array to provide the fields and values.

Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
  • Hi @Itamar Haber, thank you for your reply. Unfortunately, the nekipelov/redisclient that I am using does not support pipelining. – georgeliatsos Jan 20 '17 at 14:15
  • So use a script ;) Do you need an example of one? – Itamar Haber Jan 20 '17 at 14:27
  • My main problem is how to pass the hash keys in KEYS and the fields values to the ARGV. All my attempts so far are filling KEYS but ARGV is empty. Can you refer me to an example? Thank you! – georgeliatsos Jan 20 '17 at 15:03
  • I assume you mean an example w/ https://github.com/nekipelov/redisclient - sorry, I don't know of any... can you show what you've tried so far? – Itamar Haber Jan 20 '17 at 15:36
  • Hi @Itamar, thank you for your comment. Your reply plus looking on Youtube one of your videos for Lua, I figured out that I was missing a comma and a space between KEYS and ARGV (beginner's mistake). I will accept the answer. Thank you! – georgeliatsos Jan 22 '17 at 22:41
  • Ah yes, the comma and the space, a common pitfall... but your question suggests that you were trying to run a script from C++ code, which apparently isn't the case. Anyway, I'm glad it got resolved! – Itamar Haber Jan 23 '17 at 11:33
1

I found my answer in another question in Lua, how can I use a table as varargs (...)? .

So I just use

redis.call('hmset', KEYS[i], table.unpack(ARGV) )

and that worked for me.

Sled
  • 18,541
  • 27
  • 119
  • 168