Post on 06-Dec-2014
description
Redisdata design by usecase
1. 메시지 읽음 처리2. 인증 토큰 발행3. Redis data 설계 방법4. 데이터 설계와 고려 사항
목차
메시지 읽음 처리
이렇게 생긴거요 .
읽음 처리 요구 사항
1. 메시지 창에서 메시지의 읽음 횟수 출력 .a. 몇 명의 사용자가 메시지를 읽었는지 조회 .b. 메시지 아이디에 대한 읽음 건수 저장 .c. 메시지가 삭제되면 메시지 읽음 건수도 삭제 .
읽음 건수 데이터 설계 ( 논리 )
1. 사용자 번호 , 방 번호로 Hash 를 구성 .2. 메시지 번호를 필드로 하여 건수 저장 .3. 읽음 건수 조회는 hget 또는 hmget 을 사용 .4. 메세지 삭제 시 읽음 건수 삭제도 같이 이루어져야 함 .
읽음 건수 데이터 설계 ( 물리 )
Name KeyName Data type 포함정보
메시지 읽음 rcnt:<user>:<room> hash {message seq, read count}
구현 1. 메시지 읽음 횟수 저장 . - hincrby rcnt:<user>:<room> <message Seq> 1 2. 특정 메시지의 읽음 횟수 조회 . - hget rcnt:<user>:<room> <message Seq>3. 여러 메시지의 읽음 횟수 조회 . - hmget rcnt:<user>:<room> <message Seq> ...4. 특정 방의 메시지 읽음 횟수 조회 . - hgetall rcnt:<user>:<room>
That’s all???
배포된 바이너리에 버그가 있어서 사용자가 창을 열 때마다 API 가
호출되요 !!!!
헐 ..
!!!???
읽음 처리 요구 사항 변경
1. 메시지 창에서 메시지의 읽음 횟수 출력 .a. 몇 명의 사용자가 메시지를 읽었는지 조회 .b. 메시지 아이디에 대한 읽음 건수 저장 .c. 메시지가 삭제되면 메시지 읽음 건수도 삭제 .
2. 동일한 사용자가 API 를 여러 번 호출하더라도 읽음 횟수는 단 1 회만 증가 !
읽음 건수 데이터 설계 v2 ( 논리 )
1. 방 번호 , 메시지 번호로 구성된 키로 Set생성 .2. Set 에 메시지를 읽은 사용자의 사용자 번호 저장 .3. 데이터의 조회는 scard 명령을 사용 .
읽음 건수 데이터 설계 ( 물리 )
Name KeyName Data type 포함정보
메시지 읽음 rcnt:<user>:<room>:<message seq>
set {read user}
구현 v2(2/2)
1. 메시지 읽음 횟수 저장 - sadd rcnt:<user>:<room>:<message seq> <read user>2. 특정 메시지의 읽음 횟수 조회 - scard rcnt:<user>:<room>:<message seq>3. 여러 메시지의 읽음 횟수 조회 - scard rcnt:<user>:<room>:<message seq1> - scard rcnt:<user>:<room>:<message seq2>
구현 v2(2/2)
4. 특정 방의 읽음 횟수 조회 - scard rcnt:<user>:<room>:<message seq1> - scard rcnt:<user>:<room>:<message seq2> - scard rcnt:<user>:<room>:<message seq3> ……. ????????????
인증토큰 발행
토큰 발행 요구사항
1. 만료가 가능한 토큰을 발행한다 .2. 만료일은 발행 시간으로부터 3 일로 지정한다3. 새로운 토큰이 발행되면 이전 토큰은 만료 전까지 사용 가능하다 .4. 토큰은 부가적인 인증 정보를 가진다 .(ex. email, nickname, token issue date)
토큰 데이터 설계 ( 논리 )
1. 토큰의 만료는 redis 의 expire 를 사용 .2. 인증토큰의 부가 정보는 json 문자열로 저장 .3. token 은 사용자의 id 와 발행 시점의 timestamp 를 조합한 문자열에 sha-256 해시를 수행한 값을 사용 .4. 문자열에 token 을 키로 하여 인증 정보를 저장
토큰 데이터 설계 ( 물리 )
Name KeyName Data type 포함정보
인증토큰 token:<token string>
String {email, userno, nick}
구현1. Token 발행 - String token = sha256(id + timestamp) - setex token:<token> {'mail':'aaa@naver.com','nick':'test','userNo':'1046'} 2592002. token 검증 - get token:<token>
어때요 ? 참 쉽죠 ?
BUT!!! 그러나 !!!
토큰발행 변경 요구사항
id 별 활성 token 을 조회할 수 있게 해주세요
토큰 데이터 설계 v2 ( 논리 )
1. 만료기능은 redis 의 expire 를 사용2. 인증과 관련된 추가 정보는 json 문자열로 저장 .3. token 은 사용자의 id 와 발행 시점의 timestamp 를 조합한 문자열에 sha-256 해시를 수행한 값을 사용 .4. 문자열에 token 을 키로 하여 인증 정보를 저장 .5. 사용자 번호로 hash 를 생성 .6. hash 에 사용자 token 과 timestamp 를 저장 .
토큰 데이터 설계 v2 ( 물리 )
Name KeyName Data type
포함정보
인증토큰 token:<token string>
String {email, userno, nick}
토큰목록 tokenlist:<userNo>
hash {token, expire date}
구현 v2(1/2)
1. Token 발행 (use multi command) - String token = sha256(id + timestamp) - setex expire <token> {"email":"aaa@naver.com","nickName":"test","userNo":"1046"} 259200 - hset <userid>, <token>, timestamp
구현 v2(2/2)
2. token 검증 - get token:<token>3. 활성 token 조회 - hgetall <userid> - timestamp 를 기준으로 출력 여부 결정 .
수정이 완료 되었군요 . 운영서버로 ㄱㄱ
BUT!!! 또 그러나 !!!
HASH 내부에 만료된 token 은 언제 삭제하지 ?
redis 2.8 의 새 기능 Keyspace events
Redis Keyspace Notifications
1. 키의 변경이 발생하면 PUB/SUB 을 통해서 확인가능 . - 즉 , expire 된 키의 이름을 알 수 있음 . - config set notify-keyspace-events Ex - psubscribe "__keyevent@*"※ SUB 을 받아서 처리하는 별도의 프로그램 작성 필요 .※ 더 많은 내용 http://redis.io/topics/notifications 참조K Keyspace events, published with __keyspace@<db>__ prefix.
E Keyevent events, published with __keyevent@<db>__ prefix.
g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
...
이렇게 하여 인증 토큰을자알 구현했습니다 .
끄읕 ~~
Redis data 설계 주안점 (1/2)
1. 모든 데이터를 키에 저장할 수 있는가 ? - 키 만 조회 하여 업무를 처리할 수 있도록 구성 .2. 자료구조 Set, Hash, List 등으로 구현이 가능한가 ? - 여러개의 명령을 사용하더라도 실행시간이 O(1) 인지 . - 우리에겐 Lua 가 있다 .4. 데이터 사용 성향에 따라 다른 데이터 구조 선택 필요 . - 빠른 쓰기가 필요한지 빠른 읽기가 필요한지 - Hash 와 Sorted set 에 대한 trade 가능하면 Hash 로 .
Redis data 설계 주안점 (2/2)
5. 단순한 데이터 조회 패턴을 가지는가 ? - RDB 의 where 필터링은 불가 !!!6. 숫자 데이터가 많은가 ? - 카운터와 같은 숫자 데이터 저장에 강함 .3. Lua 사용시 전체 시간복잡도는 O(log n) 을 초과 하지 않도록 하라 .
Lua 사용 주의사항
1. 예측 불가능한 Loop 문을 사용하지 말것 . - ex) while(true) ※ Lua 스크립트의 실행은 원자성을 가짐 .
2. 에러 처리에 신경쓸것 . - ex) 조회한 데이터가 존재하는지 확인 .