Recently, when I was working on a project, I encountered a scenario: reading data from Redis, processing the data, and deleting the data. At first glance, there seems to be no problem. However, extending this scenario to multi-threaded, simultaneous execution of multiple applications may lead to repeated reading of the same data and processing of the scenario. Therefore, in order to achieve atomic manipulation of data in Redis, it is decided to introduce Lua scripts in Redis to perform data reading, data processing and data deletion operations.

1. Introduction to Redis Lua script

Lua is a lightweight scripting language written in standard C and open source. It is designed to be embedded in the application so as to provide flexible extension and customization functions for the application. Because it is widely used in: game development, standalone application scripts, Web application scripts, extensions and database plug-ins, etc. The benefits of using Lua scripts are as follows: (1) Reduce network overhead. Multiple requests can be sent in script form at a time, reducing network latency. (2) Atomic operation. Redis will execute the entire script as a whole and will not be inserted by other requests. So you don’t have to worry about race conditions during script execution, and you don’t have to use transactions. (3) reuse. The script sent by the client is perpetuated in Redis so that other clients can reuse the script without having to complete the same logic with code. Lua commands are not many, mainly the following:

  • EVAL
  • EVALSHA
  • SCRIPT LOAD – SCRIPT EXISTS
  • SCRIPT FLUSH
  • SCRIPT KILL

Related commands can be used for reference: Lua script, Lua tutorial this article is not detailed.

2. SpringBoot implements Lua script

  1. Introduction of depend on
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Copy the code
  1. Code sample
@Autowired private RedisTemplate<String,Object> redisTemplate; Public List<Object> getDataAndDel(String key, String value) {//Lua script String redisLua = "if redis. Call ('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; //Redis Key value String redisKey = "REDIS_KEY_LUA_TEST"; long nowTimeMs = System.currentTimesMillis(); List<String> keys = Collections.singletonList(redisKey); List<String> argv = Collections.singletonList(String.valueOf(nowTimeMs)); List<Object> datas = redisTemplate.execute(new RedisCallback<Long>() { @Override public List<Object> doInRedis(RedisConnection connection) throws DataAccessException { Object obj = connection.getNativeConnection(); If (obj instanceof JedisCluster) {return (List<Object>) ((JedisCluster) obj). Eval (redisLua, keys, argv); } else (obj instanceof Jedis) {return (List<Object>) ((Jedis) obj). Eval (redisLua, keys, argv); }}}); return datas; }Copy the code

Redis Lua script is best tested in Redis command line after correct, written in Java execution.

3. Reference Documents:

The Lua script

Lua scripts are used in Redis

SpringBoot+Redis method steps for executing lua scripts

EvalSha is not supported in cluster environment.