Site icon Vinsguru

Redis Lua Script With Spring Boot

Overview:

In this tutorial, I would like to show you Redis Lua Script with Spring Boot to execute a set of operations as a single transaction or to have some kind of constraints when you do Redis transactions.

Redis Lua Script:

When a client wants to execute a set of operations on Redis Database, instead of sending all the commands one by one on a network, we could create our own extensions (kind of) on Redis Database using Lua Script and execute the operations as a single transaction.

The Redis Lua Script gets compiled for the first time and then using the SHA, the loaded script can be invoked any time.

Sample Application:

We are going to consider a simple Bank application in which Redis is the primary DB. We have set of accounts. The users can transfer money from 1 account to another.

Lets see how to implement the money transfer by using Redis Lua Script with Spring Boot.

Project Setup:

Create a Spring Boot project with below dependencies.

We are going to assume that Redis maintains all the accounts in an account hash as shown below. a and b are account names and the values are the corresponding account balances.

{
  "a": "100",
  "b": "20"
}

Redis Lua Script – Money Transfer:

The following lua script is responsible for the money transfer business functionality.

--moneyTransfer.lua
local account = 'account'
local fromBalance = tonumber(redis.call('HGET', account, KEYS[1]))
local toBalance = tonumber(redis.call('HGET', account, KEYS[2]))
local amount = tonumber(ARGV[1])
if fromBalance >= amount
then
    redis.call('HSET', account, KEYS[1], fromBalance - amount)
    redis.call('HSET', account, KEYS[2], toBalance + amount)
    return true
end
return false

Redis Lua Script – Money Transfer Service:

@Configuration
public class ScriptConfig {

    @Bean
    public RedisScript<Boolean> script() {
        Resource scriptSource = new ClassPathResource("scripts/moneyTransfer.lua");
        return RedisScript.of(scriptSource, Boolean.class);
    }

}
@Service
public class MoneyTransferService {

    @Autowired
    private RedisScript<Boolean> script;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void transfer(String fromAccount, String toAccount, int amount){
        this.redisTemplate
                .execute(script, List.of(fromAccount, toAccount), String.valueOf(amount));
    }

}

Demo:

Once everything is ready, We can test as shown here.

@SpringBootApplication
public class RedisLuaScriptApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(RedisLuaScriptApplication.class, args);
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MoneyTransferService service;

    @Override
    public void run(String... args) throws Exception {

        // initialize few accounts
        this.redisTemplate.opsForHash().put("account", "a", "100");
        this.redisTemplate.opsForHash().put("account", "b",  "20");

        // transfer money with lua script
        this.service.transfer("a", "b", 20);

        // check the results
        System.out.println(
                this.redisTemplate.opsForHash().get("account", "a")
        );
        System.out.println(
                this.redisTemplate.opsForHash().get("account", "b")
        );
    }
}

Output:

80
40

Summary:

we were able to successfully demonstrate a business functionality as a single transaction by using Redis Lua Script with Spring Boot.

Learn more about Redis with Spring Boot.

The source code is available here.

Happy learning 🙂

Share This:

Exit mobile version