Trong bài viết này chúng ta sẽ cùng tìm hiểu Redis Lua Script với Spring Boot để thực hiện một tập hợp các hành động như một transaction hoặc thực hiện một số loại ràng buộc khi chúng ta thực hiện các Redis transaction.
Một số bài viết cùng chủ đề, mọi người có thể tham khảo tại đây:
- Spring Boot Cache-Aside design pattern (hướng dẫn Spring Boot Redis)
- Spring Boot Redis Transaction
Redis Lua Script
Khi chúng ta muốn thực hiện một tập hợp các hành động trên Cơ sở dữ liệu Redis, thay vì gửi lần lượt các lệnh, chúng ta có thể tạo các phần mở rộng của riêng mình trên Cơ sở dữ liệu Redis bằng cách sử dụng Lua Script và thực hiện các hành động như một transaction. Redis Lua Script được biên dịch lần đầu tiên và sau đó có thể được gọi bất kỳ khi nào.
Sample Application
Ví dụ chúng ta sẽ chuyển tiền giữa 2 tài khoản của người dùng.
Giả sử chúng ta có thông tin 2 tài khoản a và b với số dư lần lượt là 100$ và 20$ như sau:
{
"a": "100",
"b": "20"
}
Lua Script
Tập lệnh Lua Script dưới đây chịu trách nhiệm về chức năng chuyển tiền. Tập lệnh sẽ được gọi với 2 khóa (KEY) và 1 đối số (ARG). KEY1 đại diện cho tài khoản người chuyển và KEY2 đại diện cho tài khoản người nhận. Đối số là số tiền được chuyển. Nếu tài khoản người chuyển có đủ số dư thì chúng ta sẽ trừ tiền trong tài khoản người chuyển và chuyển sang tài khoản người nhận.
--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
Tập lệnh trên nằm trong src /main/resources/scripts
Redis Lua Script – Money Transfer Service
Bây giờ đến bước sử dụng file Lua Script chúng ta đã định nghĩa tập lệnh bên trên.
Đầu tiên là tạo RedisScript
Bean
@Configuration
public class ScriptConfig {
@Bean
public RedisScript<Boolean> script() {
Resource scriptSource = new ClassPathResource("scripts/moneyTransfer.lua");
return RedisScript.of(scriptSource, Boolean.class);
}
}
Tạo một class MoneyTransferService
nhận các tham số fromAccout
, toAccount
và amount
để thực hiện nghiệp vụ chuyển tiền. Chúng ta sẽ gọi RedisScript
bằng cách truyền các tham số:
@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));
}
}
Tạo file Main để chạy sample application:
@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")
);
}
}
Kết quả:
80
40
Tổng kết
Vậy là chúng ta vừa cấu hình chạy một ứng dụng Spring Boot với Lua Script. Hi vọng bài viết hữu ích với mọi người.
Nguồn: https://thenewstack.wordpress.com/2021/11/24/redis-spring-boot-with-redis-lua-script/
Follow me: thenewstack.wordpress.com