우아한테크세미나 191121 우아한레디스 by 강대명님 영상 토대로 작성한 내용입니다.
Cache
레디스를 알기 전에 Cache에 대해 먼저 알 필요가 있다.
캐시는 나중에 요청올 결과를 미리 저장해두었다가 빠르게 서비스를 해주는 것을 의미한다.
ex) Factorial같은 경우 10!을 계산한다면 1부터 10까지 다 곱하는게 아니라, 이전 값 즉 9!을 어딘가에 저장해두었다가 10만 곱해서 반환하면 된다. 즉 접근 속도에 이점이 있다.
CPU Cache
메모리는 디스크보다 용량은 훨씬 적지만, 접근 속도는 디스크보다 훨씬 빠르다.
레디스는 이 메모리에 데이터를 저장한다.
Cache 사용 패턴
Look Aside
- Server는 데이터가 존재하는지 Cache를 먼저 확인
- Cache에 데이터가 있으면 Cache에서 가져온다.
- Cache에 데이터가 없다면 DB에서 읽어온다.
- DB에서 읽어온 데이터를 Cache에 다시 저장한다.
장점: 읽기 성능 향상
Write Back
- Server는 모든 데이터를 Cache에만 저장
- Cache에 틀정 시간동안의 데이터가 저장
- Cache에 있는 데이터를 데이터를 DB에 저장
- Cache에 있는 데이터를 삭제
장점: 쓰기 성능 향상
단점: 데이터를 캐시에 저장해두고 일정 시간마다 DB에 옮겨쓰기 때문에 그 사이에 장애가 발생하거나 하는 상황이 생기면 캐시에 있는 데이터가 유실될 수 있다.
Collection
Collection이 가지는 장점
- 개발의 편의성
- 랭킹 서버를 직접 구현한다면?
- 일반적인 방법으로는 DB에 유저의 Score를 저장하고 order by로 정렬 후 읽어오기
- 개수가 많아지면 속도에 문제가 발생할 수 있다. 디스크를 사용하므로.
- Redis의 Sorted Set을 이용하면, 너무 쉽게 랭킹을 구현할 수 있음.
- 일반적인 방법으로는 DB에 유저의 Score를 저장하고 order by로 정렬 후 읽어오기
- 랭킹 서버를 직접 구현한다면?
- 개발의 난이도
- 레디스의 자료구조는 Atomic하기 때문에 자체적으론 동시성 이슈가 발생하지 않음.
- 그래도 잘못 짜면 발생함.
- ex) 레디스 내에서 싱글 스레드로만 자료구조에 접근해서 아토믹 한거지 서버 어플리케이션 단에서 꼬이려면 꼬임.
- 그래도 잘못 짜면 발생함.
- 레디스의 자료구조는 Atomic하기 때문에 자체적으론 동시성 이슈가 발생하지 않음.
Collection을 잘 이용하는 것으로, 여러가지 개발 시간을 단축시키고, 문제를 줄여줄 수 있기 때문에 Collection이 중요하다.
Redis 사용처
- Remote Data Store
- 여러 서버에서 데이터를 공유하고 싶을 때
- 주로 많이 사용하는 예시
- 인증 토큰 등을 저장(Strings 또는 hash)
- Racking 보드로 사용(Sorted Set)
- 유저 API Limit
- 작업 큐 (list)
Redis Collections
- Strings
- key / value 저장 방식
- List
- 연결 리스트 형태. 맨 앞이나 맨 뒤에서의 삽입 삭제는 빠른데 중간 삽입 삭제는 느림
- Set
- 중복 데이터 X, 데이터가 있는지 없는지만 체크하는 용도
- ex) 특정 유저를 follow하는 목록을 저장해둔다면
- Sorted Set
- Set은 순서가 없는데, Sorted Set은 Score라는걸 줘서 그 값 기준으로 정렬됨. 랭킹에 따라 순서가 바뀌길 바란다면 사용.
- sorted set의 score는 double타입이기 때문에, 값이 정확하지 않을 수 있다.
- Hash
- Key 밑에 sub key가 존재
Collection 주의 사항
- 하나의 컬렉션에 너무 많은 아이템을 담으면 좋지 않음.
- 10000개 이하 몇 천개 수준으로 유지하는게 좋음
- expire는 Collection의 item 개별로 걸리지 않고 전체 Collection에 대해서만 걸림
- 즉 해당 10000개의 아이템을 가진 Collection에 expire가 걸려있다면 그 시간 후에 10000개의 아이템이 모두 삭제.
Redis 운영
메모리 관리를 잘하자
- Redis는 In-Memory Data Store
- Physical Memory 이상을 사용하면 문제가 발생
- Swap이 있다면 Swap 사용으로 해당 메모리 Page접근시 마다 늦어짐
- Maxmemory를 설정하더라도 이보다 더 사용할 가능성이 큼.
- RSS(Resident set size)값을 모니터링 해야함.
- 많은 업체가 현재 메모리를 많이 사용해서 Swap을 쓰고 있다는 것을 모를 때가 많다고 한다. 그냥 레디스가 느려졌어요~ 한다고 함
- 메모리 파편화가 발생할 수 있음.
- 다양한 사이즈를 가지는 데이터 보다는 유사한 크기의 데이터를 가지는 경우가 유리하다.
메모리가 부족할 때는?
- Cache is Cash
- 더 메모리가 큰 장비로 Migration
- 메모리가 빡빡하면 Migration중에 문제가 발생할 수도 있다.
- 60 ~ 70 프로정도 사용중일 때 더 큰 메모리 장비로 옮겨야 한다.
- 있는 데이터 줄이기
- 데이터를 일정 수준에서만 사용하도록 특정 데이터를 줄임
- 다만 이미 Swap을 사용중이라면, 프로세스를 재시작 해야함.
- 메모리를 줄이기 위한 설계
- 기본적으로 Collection들은 다음과 같은 자료구조를 사용
- Hash → HashTable을 하나 더 사용
- Sorted Set → Skiplist와 HashTable을 이용
- Set → HashTable 사용
- 해당 자료구조들은 메모리를 많이 사용함.
- Ziplist를 이용하자
- ziplist
- In Memory특성 상, 적은 개수라면 선형 탐색을 하더라도 빠르다.
- List, hash, sorted set 등을 ziplist로 대체해서 처리를 하는 설정이 존재
- ziplist
- 기본적으로 Collection들은 다음과 같은 자료구조를 사용
O(n)관련 명령어는 주의하자.
- Redis는 Single Threaded
- 그러면 Redis가 동시에 여러 개의 명령을 처리할 수 있을까?
- 참고로 단순한 get / set의 경우, 초당 10만 TPS이상 가능 (CPU 속도에 영향받음)
- 한번에 하나의 명령만 수행 가능
- 긴 시간이 필요한 명령을 수행하면, 뒤에 들어오는 명령들도 다 그 시간만큼 대기해야해서 망함
- 대표적인 O(n) 명령들
- keys
- flushall, flushdb
- delete collections
- get all collections
- 대표적인 실수 사례
- 모니터링 스크립트가 주기적으로 keys를 호출…
- 아이템이 몇만개 든 hash, sorted set, set에서 모든 데이터를 가져오는 경우
- keys는 어떻게 대체할 것인가?
- scan 명령을 사용하는 것으로 하나의 긴 명령을 짧은 여러 번의 명령으로 바꿀 수 있다.
- 그 사이사이에 다른 명령들이 수만건씩 처리 가능
- scan 명령을 사용하는 것으로 하나의 긴 명령을 짧은 여러 번의 명령으로 바꿀 수 있다.
- Collection의 모든 item을 가져와할 때?
- Collection의 일부만 가져오거나
- sorted set
- 큰 Collection을 작은 여러 개의 Collection으로 나눠서 저장 (샤딩)
- 하나당 몇천개 안쪽으로 저장하는게 좋음
- Collection의 일부만 가져오거나
Redis Replication
- Async Replication
- Replication Lag이 발생할 수 있다.
- ‘Replicaof’(≥ 5.0.0) or ‘slaveof’ 명령으로 설정 가능
replicaof hostname port
- DBMS로 보면 statement replication이 유사
- Replication 설정 과정
- Secondary에 replicaof or slaveof 명령을 전달
- Secondary에 Primary에 sync 명령 전달
- Primary는 현재 메모리 상태를 저장하기 위해 Fork
- Fork한 프로세서는 현재 메모리 정보를 disk에 dump
- 해당 정보를 secondary에 전달
- Fork이후의 데이터를 secondary에 계속 전달
- Replication 주의사항
- Repliaction 과정에서 fork가 발생하므로 메모리 부족이 발생할 수 있다.
- redis-cli —rdb 명령은 현재 상태의 메모리 스냅샷을 가져오므로 같은 문제를 발생시킴
- AWS나 클라우드의 Redis는 좀 다르게 구현되어서 좀더 해당 부분이 안정적
redis.conf 권장 설정
- maxclient 설정 50000
- RDB / AOF 설정 off
- 특정 commands disable
- keys
- 전체 장애의 90프로 이상이 keys와 save설정을 사용해서 발생
- 적절한 ziplist 설정
Redis 용도?
- 데이터의 특성에 따라서 선택할 수 있는 방법이 달라진다.
- Cache 용도로 사용할 경우 문제가 적게 발생
- Redis가 문제가 있을 때 DB 등의 부하가 어느 정도 증가하는지 확인 필요
- Persistent Store의 경우
- 무조건 Primary / Secondary 구조로 구성이 필요함
- 메모리를 절대로 빡빡하게 사용하면 안됨
- 정기적인 migration이 필요
- 가능하면 자동화 툴 만들어서 이용
- RDB / AOF 가 필요하다면 Secondary에서만 구동
'Redis' 카테고리의 다른 글
[Redis] 다건 조회를 캐싱할 때 고민했던 것들 (1) | 2023.02.21 |
---|---|
Docker로 레디스 로컬 환경 간편하게 세팅하기 (0) | 2022.10.26 |