중요성 

  • 동시성을 해결할 수 있는 해결책으로, lua script에 적힌 명령어는 redis에서 원자적으로 실행된다. 즉, 각 명령어 사이에 다른 명령어가 실행되지 않는다.
  • 여러 번 redis 서버에 요청을 보내지 않고 한 번만 요청을 보내서 여러 명령어를 수행할 수 있다.

 

Lua 문법 :

 

redis에서 사용 방법 

  • script load "<lua script 내용>"을 실행함으로써 lua script로서 실행할 명령어들을 메모리에 로드할 수 있다.
  • 이 때 반환되는 값은 sha1로 해당 lua script를 지칭하는 값이다.
  • evalsha <sha1> <num> 명령어를 입력하면 해당 sha1 값에 해당하는 lua script가 실행된다. 여기서 <num>은 키의 개수를 뜻하며 0이 아닌 숫자일 시에 바로 뒤에 키값을 써주고, 이후에 일반적인 인수를 넣어준다.
  • lua script에서 일반적인 인수를 받는 방법은 ARGV[index]을 이용하면 된다. ARGV는 전역변수로 인수에 따라 자동으로 선언된다.
  • redis에서 ARGV에 값을 줄 때는 무조건 string 값으로 넘겨줘야 하며, lua script 내부에서도 string 타입이 된다.
script load 'return 1 + ARGV[1] + tonumber(ARGV[2])'
evalsha <sha1> 0 '1' '2' ...
  • redis에 존재하는 명령어를 사용하려면 redis.call('명령어', KEYS[index], 인자1, ...)을 이용하면 된다.
  • 이 때 KEYS 또한 전역변수로, redis에서 전송한 값을 string으로 받는다.
script load 'return redis.call("GET", keys[1])'
evalsha <sha1> 1 color // KEYS = { 'color' }
  • return redis.call("GET", "color")로 접근해도 실행은 가능하지만, 이면에서 버그가 생기기 시작하고 문제를 일으키게 되므로 사용을 지양해야 한다.

 

spring에서 사용 방법

  • DefaultRedisScript를 싱글 인스턴스로 관리하여 동일 script에 대해 동일한 sha1 값을 사용하도록 설정한다.
@Bean
    public DefaultRedisScript<Void> hsetxxScript() {
        String luaScript =
                "local key = KEYS[1] " +
                "local fieldKey = ARGV[1] " +
                "local fieldValue = ARGV[2] " +
                "if redis.call('EXISTS', key) == 1 then " +
                "    redis.call('HSET', key, fieldKey, fieldValue) " +
                "end";

        return new DefaultRedisScript<>(luaScript, Void.class);
    }
  • 로드해 놓은 script를 사용한다.

 

...

private final DefaultRedisScript<Void> hsetxxScript;

...

public void putFieldIfPresence(String key, String fieldKey, String fieldValue) {
    stringRedisTemplate.execute(hsetxxScript, singletonList(key), fieldKey, fieldValue);
}
  • 내부적으로 전달하는 값을 byte 배열로 변경한다.
  • RedisTemplate<String, Long>과 같이 설정하고 값을 넣으면 해당 객체의 타입도 저장되는데, Lua Script에서 저장될 때는 Long 값 자체에 대한 byte값이 저장되므로 일치하지 않게 된다.
  • 따라서 Lua Script를 사용할 때에는 무조건 RedisTemplate<String, String>만을 사용하자.

'Database > Redis' 카테고리의 다른 글

RedisStack  (0) 2024.11.06
메모리 정책 in redis  (0) 2024.11.05
Lock으로 동시성 관리하기 (with. redis)  (0) 2024.10.17
List 타입 명령어  (0) 2024.10.09
HyperLogsLogs 타입 명령어  (0) 2024.10.09

+ Recent posts