Redis Lua Script를 활용 예

2021. 4. 11. 03:26 NoSQL/redis

활용

 

목표 : 어떤 유저들의 상태를 비교하여 값이 같다면 리스트에서 삭제하는 기능을 테스트해 보겠습니다.

Redis에서 Insert시 unique를 보장하는 것은 Sets 입니다. Sets에 입력되는 값들은 단순 key 식별자가 가능해서 해당 key들의 상태 값들의 변경을 담을 수 없습니다. 그래서 Sets에서는 특정 key값이 이미 존재 하는지, 존재 하지 않는지를 식별하는 tree로 사용하고, 해당 key값이 가지는 부가적인 상태들을 Hash에 담아 관리 하며, 특정 값이 삭제할 상태가 되었을때 Sets와 Hashs에 존재 하는 값을 삭제 하는 것을 구현해 보겠습니다.

 

상황 설정

Guild Chatting Room 의 번호를 1,2,3..(Guild의 PK) 으로 관리 합니다.

FrontEnd에서는 L4로 분배된 Gate Server들이 존재 하며, Backend에는 Chatting Svr Room을 관리하는 Chatting Server이 존재 합니다.

Gate Server와 Chatting Server는 Redis를 통해 Guild Chatting Room을 생성 파괴 관리 합니다.

 

 

Redis활용 예를 들기 위한 구조이니 pub/sub 을 이용한 방식등에 대한 의구심은 버리고 참고 하시기 바랍니다.

Gate Server는 L4에 의해 Load Balance되며 Chatting Server 또한 Scale out 되어 있으며 Gate Server에 의해 Load Balance됩니다.

 

sets key 이름 : sets:guildroom.list

hashes key 형식 : hashs:guild:room.길드번호

field :

sn : Gate Server에서 Room 생성시 발급하는 생성 serial number

svr : Chatting Server의 고유 svr 번호 (1,2,3.... )

state : Room의 상태, 0:생성 중 1:생성완료

ct : 생성 시간

jt : Gate Server에서 redis data Access 시간

 

생성 script

-- Sets에 key값이 존재하지 않는다면 Hashs Set, 존재한다면 실패를 리턴 합니다.

local result = redis.call('SADD', KEYS[1], ARGV[1])

   if result == 1 then
      redis.call('HMSET', KEYS[2], 'sn', ARGV[2], 'svr', ARGV[3], 'state', 0, 'ct', ARGV[4], 'jt', ARGV[5])
      return redis.call('HGETALL', KEYS[2])
   end
return redis.call('HGETALL', KEYS[2])

 

 

script load 를 통해서 sha 값을 받습니다.

 script load "local result = redis.call('SADD', KEYS[1], ARGV[1]) if result == 1 then redis.call('HMSET', KEYS[2], 'sn', ARGV[2], 'svr', ARGV[3], 'state', 0, 'ct', ARGV[4], 'jt', ARGV[5]) return redis.call('HGETALL', KEYS[2]) end return redis.call('HGETALL', KEYS[2])"


 

결과 :

"5c0fa0adbf333189964e32e982b337089c5d5534"

     

User가 진입하면 User 의 Guild PK를 조회 한 후 (생략) Guild Chatting Room 정보를 조회 합니다. Guild 번호는 1004로 가정합니다.

 

evalsha 5c0fa0adbf333189964e32e982b337089c5d5534 2 sets:guildroom.list hashs:guild:room.1004 1004 gr012231 2 1485251980 1485251980

 

결과 :

 1)  "sn"
 2)  "gr012231"
 3)  "svr"
 4)  "2"
 5)  "state"
 6)  "0"
 7)  "ct"
 8)  "1485251980"
 9)  "jt"
 10)  "1485251980"

 

Redis에는 다음과 같이 입력 됩니다.

 

Guild Room List를 관리하는 Sets에 1004번 길드 삽입.

 

Guild Room의 상세 정보를 담은 Hashes에 길드 정보 삽입.

 

생성 후 Gate Server에서는 Chatting Server에 Guild Chatting Room을 할당 하고 관리 해주기를 요청 합니다.

 

Chatting Server에서 길드 룸 할당 후 Redis에 생성 상태로 변경 하는 Scrip

 

local result = redis.call('SISMEMBER', KEYS[1], ARGV[1])

if result == 1 then
   local sn = redis.call('HGET', KEYS[2], 'sn')
   if sn == ARGV[2] then
      redis.call('HSET', KEYS[2], 'state', 1)
      return 1
   end 
end

return 0

 

script load 를 통해서 sha 값을 받습니다.

 script load "local result = redis.call('SISMEMBER', KEYS[1], ARGV[1]) if result == 1 then local sn = redis.call('HGET', KEYS[2], 'sn') if sn == ARGV[2] then redis.call('HSET', KEYS[2], 'state', 1) return 1 end end return 0"

 

결과 :

"02dd85d7abc743eb77a1b5eea48eaeb34ed93917"

 

Chatting Server에서 Room생성 처리후 Redis에 상태를 갱신 합니다.

evalsha 02dd85d7abc743eb77a1b5eea48eaeb34ed93917 2 sets:guildroom.list hashs:guild:room.1004 1004 gr012231

 

결과 :

"1"

 

Redis에는 다음과 같이 입력 됩니다.

 

 

Redis에 evalsha 한 결과가 "0"이라면 Room 생성 실패 처리로 예외 처리 하면 됩니다.

 

Redis에서는 RDBMS와 같이 Lock 처리 후 여러 연산을 하는 기능을 지원 하지 않습니다. Lua script를 사용하면 여러 명령어를 인터럽트 없이 사용 가능합니다. 또한 Strings, Lists, Sets, Sorted Sets, Hashes의 고유 특징들을 교차 사용하여 다양한 조건 처리가 가능 합니다.

 

출처 : code-factory.tistory.com/14?category=724511

'NoSQL > redis' 카테고리의 다른 글

[Redis, 레디스] 레디스 소개 및 아키텍처, 주의할 점(Redis Overview, Redis Architecture, Tool Tip)  (0) 2023.04.25
Redis - 조회 명령어 정리  (0) 2022.05.09
Redis 의 Lua Script 활용  (0) 2021.04.11
Redis cluster  (0) 2021.04.11
redis Strings  (0) 2021.04.11
redis Lists  (0) 2021.04.11
redis Sorted Sets  (0) 2021.04.11
redis Sets  (0) 2021.04.11