모바일 게임 데이터를 Redis에 어떻게 저장하지

레디스에 대한 개념 설명이나, 설치법, 고가용성을 얻기 위한 정보들은 많이 있습니다. 하지만 정작 레디스에 데이터를 어떻게 저장하면 좋을지에 대한 정보들은 찾기가 힘듭니다. 그래서 아직 사용해본 기간은 짧지만 그동안 사용하면서 얻은 팁을 공유하고자 합니다.

1. value에는 값을 하나만 저장하자

luna1x라는 유저의 계정정보를 아래처럼 value에 여러 값을 묶어서 저장 할 수 있습니다.

key                               field                value
luna1x                          account           { gold : 4000, cash : 3000 }

이렇게 value에 여러 값을 묶어서 저장할 경우 문제점은 크게 4가지 입니다.

성능 : gold정보만 필요한 상황에서도 cash정보까지 같이 읽어와야 하고, gold정보만 갱신하고 싶어도 cash정보까지 다 갱신 해야 합니다.
실수를 유발하는 디자인 : 전체를 불러와서 일부분만 수정후 덮어 쓰는 방식은, gold를 변경후 cash를 변경하는 상황에서 개발자가 실수로 gold 변경전 내역의 데이터로 cash만 변경후 덮어 써서 gold변경 내역을 날리는 실수를 하게 만들기 쉽습니다.
atomic : incr, decr 같은 atomic한 커맨드를 사용할 수 없게 됩니다.
transaction : watch, multi, exec 같은 transaction에 관련된 커맨드를 사용할 수 없게 됩니다.

그래서 아래 처럼 value에는 하나의 값만 저장해야 합니다.

key                               field                value
luna1x:account            gold                 4000
—————————–cash                3000

2. 숫자  데이터의 변경은 set대신 incr, decr를 사용하자

luna1x 유저의 gold 1000 증가를 set을 사용해서 할수도 있고 incr를 사용해서 할수도 있습니다. set 방식은 gold값을 가지고 와서 1000을 더한다음 그 값을 덮어 쓰는 방식이고, incr는 atomic하게 1000을 증가하는 방식입니다. gold가 레이스 컨디션일때 set을 사용하게 되면 잘못된 값을 덮어 쓸 확률이 높지만, incr는 atomic하기 때문에 문제가 발생하지 않게됩니다. atomic한 command와 그렇지 않은 command를 둘다 사용할수 있다면 꼭 atomic한 command를 사용 하세요.

3. scaleout이 필요한 데이터와 그렇지 않은 데이터를 구분하자

가장 쉬운 구분법은 유저수에 비례해서 늘어나는 데이터이냐 그렇지 않느냐로 구분하면 됩니다.
유저수에 비례하는 데이터 : 아이템, 계정, 길드, 우편, 퀘스트 진행사항 등등
유저수와 비례하지 않는 데이터 : 공지사항, 이벤트(경험치,드랍율) 배율  등등

유저수와 비례하지 않는 데이터는 scaleout 용도가 아닌 레디스에 저장하고, 유저수에 비례하는 데이터는 sacleout  용도의 레디스에 저장하기 위해 데이터의 종류를 구분해 둡니다.

4. scaleout을 위해 redis를 구분해서 사용하자

common : scaleout이 필요없는 데이터 저장, scaleout이 필요한 데이터의 key 저장
cellFinder : scaleout이 필요한 데이터가 저장된 cell위치를 key로 찾을수 있게 저장
cell1, cell2, cell3… : scaleout이 필요한 데이터 저장

예를들어 luna1x라는 유저의 가입 처리는 아래와 같습니다.
1. luna1x와 매칭되는 account:3000 같은 key를 만들어서 common에 저장
2. account:3000 key에 관련된 정보를 몇번 cell에 저장할지 결정하고 cellFinder에 저장
3. 실제 luna1x의 가입일, 보유한 캐쉬및 골드 같은 데이터는 2번에서 결정된 cell에 저장

가입 후 로그인 처리는 아래와 같습니다.
1. luna1x에 매칭되는 account:3000 key를 common에서 찾음
2. account:3000 key가 몇번 cell에 저장되어 있는지 cellFinder에서 찾음
3. 2번에서 찾은 cell에서 account:3000에 해당하는 정보를 읽음

위의 팁들을 적용해서 레디스에 저장한 예

[common]
key                               value
account:maxKey          3001
guild:maxKey                253
notice                            hello world

key                               field                value
account:keyFinder       luna1x             account:3000
——————————jane                account:3001
guild:keyFinder             onepiece        guild:252

[cellfinder]
key                               value
account:3000               1
account:3001               2
guild252                       1

[cell1]
key                               field                value
account:3000               name              luna1x
——————————level               3
——————————gold               4000
——————————guild               guild:252
——————————lock                gold

guild:252                       name            onepiece
——————————notice           득템 하세요
——————————leader           account:3000

account:3000:inven     11(물약ID)     10(수량)
——————————52(갑옷ID)     1(수량)

key                               member
account:3000:friend     account:3001
guild:252:member        account:3000, account:3001

[cell2]
key                               field                value
account:3001               name              jane
——————————level               5
——————————gold               4000
——————————guild              guild:252

Leave a comment