Small problems with Redis and Lua – original link

The problem

A Redis key or field where get or hget does not exist returns nil explicitly on the terminal, similar to the following

127.0.0.1:6379 > get test_version (nil)Copy the code

Nil is used to determine whether a value obtained from a Lua script is null, but this is not the case, as shown below:

127.0.0.1:6379> get test_version
(nil)
127.0.0.1:6379> EVAL "local a = redis.call('get',KEYS[1]) print(a) if a == 'nil' then return 1 else return 0 end" 1 test_version test_version
(integer) 0
Copy the code

What is the data type of the result returned by executing the Lua script

127.0.0.1:6379> get test_version
(nil)
127.0.0.1:6379> EVAL "local a = redis.call('get',KEYS[1]) return type(a)" 1 test_version test_version
"boolean"
Copy the code

As you can see from the script above, when Redis returns a result of (nil), its real data type is Boolean, so we can tell that nil is problematic.

Redis official documentation

Look through official documents and find the following passage,

Redis to Lua conversion table.

  • Redis integer reply -> Lua number
  • Redis bulk reply -> Lua string
  • Redis multi bulk reply -> Lua table (may have other Redis data types nested)
  • Redis status reply -> Lua table with a single ok field containing the status
  • Redis error reply -> Lua table with a single err field containing the error
  • Redis Nil bulk reply and Nil multi bulk reply -> Lua false boolean type

Lua to Redis conversion table.

  • Lua number -> Redis integer reply (the number is converted into an integer)
  • Lua string -> Redis bulk reply
  • Lua table (array) -> Redis multi bulk reply (truncated to the first nil inside the Lua array if any)
  • Lua table with a single ok field -> Redis status reply
  • Lua table with a single err field -> Redis error reply
  • Lua boolean false -> Redis Nil bulk reply.

The solution

We know from the official documentation that to determine whether the Lua script returns a null value, we should directly determine true/false. Modify the judgment script as shown below

127.0.0.1:6379> get test_version
(nil)
127.0.0.1:6379>  EVAL "local a = redis.call('get',KEYS[1]) if a == false then return 'empty' else return 'not empty' end" 1 test_version test_version
"empty"
Copy the code

Pay attention to our