[우아한테크세미나] 강대명님의 '우아한레디스' 정리
- Redis 소개
- In-Memory Data Structure Store
- Open Source(BSD 3 License)
- Support data structures
- Strings, set, sorted-set, hashes, list
- Hyperloglog, bitmap, geospatial index
- Stream
- Only 1 Committer
Cache ?
- 나중에 요청을 결과를 미리 저장해두었다가 빠르게 서비스를 해주는 것
- 캐시의 구조
- 1) insert 쿼리를 1번씩 500번 날리는 것?
- 2) insert 쿼리를 500개를 한번에 날리는 것? -> batch 작업이라고 하여 2)번이 훨씬 빠름
- Write Back의 단점?
- 캐시에 먼저 저장하기 때문에, 장애가 생기면 데이터가 사라질 위험이 있음
- 왜 Collection이 중요한가?
- 개발의 편의성
- ex) 랭킹 서버를 직접 구현?
- 가장 간단한 방법? DB에 유저의 Score를 저장하고 Score로 order by로 정렬후 읽어오기
- 개수가 많아지면 속도에 문제가 발생 할 수 있음 -> 결국 디스크를 사용하므로 -> in-memory 기준으로 랭킹서버의 구현이 필요
- Redis의 'sorted set'을 이용하면, 랭킹 구현 가능
- 다만 가져다 사용하면 거기의 한계에 종속적
- ex) 랭킹 서버를 직접 구현?
- 개발의 난이도
- ex) 친구리스 관리?
- 친구 리스트를 key/value 형태로 저장?
- Redis의 경우는 자료구조가 Atomic 하기 때문에, 해당 Race Condition을 피할 수 있음 (그래도 잘못짜면 발생함)
- ex) 친구리스 관리?
- 외부의 collection을 잘 이용하는 것으로, 여러가지 개발 시간을 단축시키고, 문제를 줄여줄 수 있기 때문에 collection이 중요
- 개발의 편의성
- Redis는 어디 사용?
- Remote Data Store
- A서버, B서버, C서버에서 데이터를 공유하고 싶을 때
- 한대에서만 필요하다면, 전역 변수 사용?
- Redis 자체가 Atomic을 보장
- 주로 많이 쓰는 곳?
- 인증 토큰 등을 저장(Strings or hash)
- Ranking 보드로 사용(Sorted Set)
- 유저 API Limit
- 좌표(list)
- Remote Data Store
- Redis Collecitons
- Strings : key/value 저장방식 -> 단일, 멀티 key
- 단일 Key 사용법 -> 키값으로 뭘 사용할건지가 중요
- Set <key> <value>
- Set token:1234567 asdfasdf
- Get <key>
- Get token:1234567
- Set <key> <value>
- 단일 Key 사용법 -> 키값으로 뭘 사용할건지가 중요
- List
- Lpush<key><A>
- Rpush<key><B>
- Lpop<key>
- Rpop<key>
- Set
- SADD<key><value>
- value가 이미 key에 있으면 추가 X
- SMEMBERS<key>
- 모든 value 돌려줌
- SISMEMBER<key><value>
- value가 존재하면 1, 없으면 0
- 특정 유저가 follow 하는 목록을 저장해둔다면?
- SADD<key><value>
- Sorted Set
- ZADD <key><Score><value>
- value가 이미 key에 있으면 해당 score로 변경
- ZRANGE <key><Startindex><EndIndex>
- 해당 인덱스 범위 값을 모두 반환
- 유저랭킹 보드로 사용 가능
- sorted sets의 score는 double 타입이기 때문에, 값이 정확하지 않을 수 있음
- ZADD <key><Score><value>
- Hash
- Hmset<key><subkey1><value1><subkey2><value2>
- Hgetall<key>
- 해당 key의 모든 subkey와 value를 가져옴
- Hget<key><subkey>
- Hmget<key><subkey1>...<subkeyN>
- Collection 주의 사항
- 하나의 컬렉션에 너무 많은 아이템을 담으로 좋지 않음
- 10000개 이하 몇천개 수준으로 유지하는게 좋음
- Expire는 Colleciton의 item 개별로 걸리지 않고 전체 collection에 대해서만 걸림
- 즉, 해당 10000개의 아이템을 가진 collection에 expire가 걸려있다면 그 시간 후에 10000개의 아이템이 모두 삭제
- 하나의 컬렉션에 너무 많은 아이템을 담으로 좋지 않음
- Strings : key/value 저장방식 -> 단일, 멀티 key
- Redis 운영
- 메모리 관리를 잘하자
- Physical Memory 이상을 사용하면 문제가 발생
- Swap이 있다면 Swap 사용으로 해당 메모리 page접근시 마다 늦어짐
- Swap이 없다면?
- Maxmemory를 설정하더라도 이보다 더 사용할 가능성이 큼
- RSS 값을 모니터링 해야함
- 큰 메모리를 사용하는 instance 하나보다는 적은 메모리를 사용하는 instance 여러개가 안전함
- 다양한 사이즈를 가지는 데이터 보다는 유사한 크기의 데이터를 가지는 경우가 유리
- Physical Memory 이상을 사용하면 문제가 발생
- 메모리 관리를 잘하자
- O(N) 관련 명령어는 주의하자
- 레디스는 싱글 스레드 -> 한번에 하나의 명령만 수행 가능
- 레디스가 동시에 여러 개의 명령을 처리할 수 있나?
- 참고로 단순한 get/set의 경우, 초당 10만 TPS 이상 가능(CPU 영향 받음)
- (대표적) KEYS, FLUSHALL, FLUSHDB, Delete Colleciotns, Get All Collections -> 이런 명령어 조심!
- key가 백만개 이상인데 확인을 위해 keys 명령어를 사용하는 경우
- 모니터링 스크립트가 일초에 한번씩 keys를 호출하는 경우
- 아이템이 몇만개 든 hash, sorted set, set에서 모든 데이터를 가져오는 경우
- key가 백만개 이상인데 확인을 위해 keys 명령어를 사용하는 경우
- KEYS -> scan 명령어를 사용하는 것으로 하나의 긴 명령을 짧은, 여러번의 명령으로 바꾸기 가능
- Colleciton의 모든 item을 가져와야 할 때?
- collection의 일부만 가져오거나
- 큰 컬렉션을 작은 여러개의 컬렉션으로 나눠서 저장
- 레디스는 싱글 스레드 -> 한번에 하나의 명령만 수행 가능
- Replication
- Async Replication
- Replication Lag 발생할 수 있음
- 'Replicaof'(>=5.0.0) or 'slaveof' 명령으로 설정 가능
- Replicof hostname port
- DBMS로 보면 statement replication가 유사
- Async Replication
- Redis Replication 시 주의할 점
- Replication 과정에서 fork가 발생하므로 메모리 부족이 발생할 수 있음
- Redis-cli --rdb 명령은 현재 상태의 메모리 스냅샷을 가져오므로 같은 문제를 발생시킴
- AWS나 클라우드의 Redis는 좀 다르게 구현되어서 좀더 해당 부분이 안정적
- 많은 대수의 Redis 서버가 Replica를 두고 있다면?
- 네트웍 이슈나, 사람의 작업으로 동시에 replication이 재시도 되도록 하면 문제가 발생할 수 있음
- ex) 같은 네트워크안에서 30GB를 쓰는 Redis Master 100대 정도가 리플리케이션을 동시에 재시작하면?
(+) 다루지 않는 내용이 따로 공부할 내용
- Redis Persistence(RDB, AOF)
- Redis Pub/Sub
- Redis Stream
- 확률적 자료구조
- Hyperloglog
- Redis Module