☁ Green Panda
Posted on July 25, 2022
Context
Do you know that you can run a script in Redis? If you don't know maybe it is time to try it out. This scripting ability is intended to optimize performance for Redis operation. However, you probably can achieve the same performance using Redis Pipeline feature. Depending on the use cases, this scripting ability is available if you have very compelling use case.
This article will show you various Redis Lua scripts use case that will make your life easier and its potential use cases where it might fit in daily life.
1. HGet Members
Description
If you have a hash and a set, where a set defines specific hash keys.
Example
Let's say you have vehicles, 3 Honda cars, 1 Mercedes car, and 2 Scooters. We can this script to pull the counts of the Cars.
> hset cars honda 3
(integer) 1
> hset cars mercedes 1
(integer) 1
> hset motorbikes scooters 1
(integer) 1
> sadd cars honda mercedes
(integer) 2
> evalsha 700c06c5ce9835bf9eef2198c8bc4d268b3b5095 2 cars produce
1) 1) "honda"
2) "3"
2) 1) "mercedes"
2) "1"
Lua source:
local fields = redis.call("SMEMBERS", KEYS[2])
local values = redis.call("HMGET", KEYS[1], unpack(fields))
local result = {}
for i,k in ipairs(fields) do result[i] = {k, values[i]} end
return result
2. HINCR IF-EXISTS
Description
If you need to increment existing value in Hash map with additional check on the key existance.
Example
> evalsha 3cb0d65c399fda8a1d4eb93b2fe85311671bc969 1 top_scorer budi 1
(nil)
> hset top_scorer budi 80
(integer) 1
> evalsha 3cb0d65c399fda8a1d4eb93b2fe85311671bc969 1 top_scorer budi 1
(integer) 91
> evalsha 3cb0d65c399fda8a1d4eb93b2fe85311671bc969 1 top_scorer budi 1
(integer) 92
Lua source:
if redis.call("HEXISTS", KEYS[1], ARGV[1]) == 1 then
return redis.call("HINCRBY", KEYS[1], ARGV[1], ARGV[2])
else
return nil
end
3. HMSET-Extended
Description
In hash set, you usually need to set value one by one. You can leverage Lua to set multiple key from the args.
Example
> evalsha 8c4bbf1b37784149128a5b96e55073538a7401d9 1 mykey foo 1 bar 2
(integer) 1
> hgetall mykey
1) "foo"
2) "1"
3) "bar"
4) "2"
> evalsha 8c4bbf1b37784149128a5b96e55073538a7401d9 1 mykey foo 1 bar 3 baz 4
(integer) 0
> hgetall mykey
1) "foo"
2) "1"
3) "bar"
4) "2"
Lua source:
if redis.call('exists', KEYS[1]) == 0 then
redis.call('hmset', KEYS[1], unpack(ARGV))
return 1
end
return 0
4. Simple Rate Limit
Description
If you use Redis for rate limiting, Lua can help you putting together logic your rate limit logic.
Example
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 0
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 0
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 0
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 0
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 0
> evalsha 089ccf077629d371793d5e928a3f06e9e483eb08 1 ratelimit:127.0.0.1 5 10000
(integer) 1
Lua source:
local cnt = redis.call('INCR', KEYS[1])
if cnt > tonumber(ARGV[1])
then
return 1
end
if cnt == 1
then
redis.call('PEXPIRE', KEYS[1], ARGV[2])
end
return 0
5. Value in Multiple Sets
Description
If you have use case, where you need to check value in multiple sets. This Lua script is definitely helpful for the implementation and avoid networking call.
Example
> sadd users alice bob
(integer) 2
> sadd admin jenny
(integer) 1
> evalsha d7550c872f553141096d5134c027af5eeed283db 2 users admin alice
(integer) 1
> evalsha d7550c872f553141096d5134c027af5eeed283db 3 users admin guests jenny
(integer) 1
> evalsha d7550c872f553141096d5134c027af5eeed283db 2 users admin abner
(integer) 0
Lua source:
-- Is an item in any of several sets? Call with:
-- EVALSHA n set1 set2 ... setn key
for i=1,#KEYS do
if redis.call('sismember', KEYS[i], ARGV[1]) == 1 then
return 1
end
end
return 0
Posted on July 25, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.