본문 바로가기

programming

[Redis] lua script를 활용한 SetIfNewer(upsert) 예제

Redis Lua script call

REDIS lua script: ( https://redis.io/commands/eval )

  • command: EVAL
    • 아래처럼 스크립트를 매번 호출할 때마다 포함하여 호출할 수 있다.
    • 아래 코드의 HGET, HSET은 트랜잭션 처리가 되어 수행된다.
        > EVAL 'if redis.call("HGET", KEYS[1], ARGV[1]) < ARGV[2] then return redis.call("HSET",KEYS[1], ARGV[1], ARGV[2]) end return -1' 2 hashtable -1 createdate 293891
  • command: EVALSHA
    • 위 처럼 호출할 수도 있고, 한 번 호출한 스크립트에 대해서 해시값으로 접근할 수 있다. (매번 스크립트를 보내면 네트워크 부하가 발생할 수 있으므로)
    • 이는 레디스 내부에서 스크립트를 호출 할 때, 스크립트 전체를 sha1 형태로 만들고 이를 set 과 같은 저장소에 담아두는데, 이것이 포인터 역할을 한다.
    • 여기서 eval 을 호출하거나 script를 호출하면 (둘 중 하나) 레디스 내부 구조에 해당 스크립트가 캐싱되며, 이를 evalsha를 이용하여 네트워크 부하를 eval을 호출하는 것보다 줄일 수 있다.
    • 이를 활용한 사용법은 아래와 같다.
        localhost:0> eval 'return redis.call("GET", KEYS[1])' 1 test 0
        "d1ad8397c172dc0a63e271f0c4c4250ca8d5d1fb"

        localhost:0> script load 'return redis.call("GET", KEYS[1])'
        "d1ad8397c172dc0a63e271f0c4c4250ca8d5d1fb"

        localhost:0> evalsha d1ad8397c172dc0a63e271f0c4c4250ca8d5d1fb 1 test
        "asdfasdf"
  • command: SCRIPT
    • SCRIPT FLUSH
      • 레디스에 저장된 스크립트 캐시를 지운다.
    • SCRIPT EXISTS sha1 sha2 ... shaN
      • 해시값을 넣어서 현재 레디스에 value를 이름으로 가지는 스크립트가 있는지 확인한다.
    • SCRIPT LOAD script
      • 신규 스크립트를 캐싱한다.
    • SCRIPT KILL
      • 현재 호출되어 수행되고 있는 스크립트 작업을 중지시킨다.
  • lua script sample: HSETIfNewer (https://gist.github.com/gordonlee/0a309bbca394fc8e328748e25af614b8)