인메모리 키-값 형태의저장소
고성능
각종 모니터링 및 알림 기능
관리형 서비스
Redis와 Memcached 지원
Amazon
ElastiCache
6.
관리형 서비스 =자동화된 운영이 가능
EC2상에서 Redis/Memcached 직접 운영하는 경우 ElastiCache 사용하는 경우
7.
Memcached vs Redis
•수평적인 문자열 캐시
• 멀티스레드
• 디스크에 저장 안함
• 단순한 관리
• 수평적 확장이 쉬움
• 싱글 스레드
• 원자적 연산 지원
• 다양한 자료 구조 지원
• Pub/Sub 기능 지원
• 읽기 복제본 지원
• Failover 지원
# PHP
$server_endpoint ="mycache.z2vq55.cfg.usw2.cache.amazonaws.com";
$cache = new Memcached();
$cache->setOption(
Memcached::OPT_CLIENT_MODE, Memcached::DYNAMIC_CLIENT_MODE);
# Set config endpoint as only server
$cache->addServer($server_endpoint, 11211);
DIY: http://bit.ly/elasticache-autodisc
Memcached Node Auto-Discovery
15.
Thundering Herd
주요 원인
•APP시작시 캐시 채우기
• 노드의 추가/삭제
• 캐시 키의 무효화 (TTL out)
• 캐시 메모리 꽉 참
https://en.wikipedia.org/wiki/Thundering_herd_problem
캐시 미스가 순간적으로 많이 발
생하면 DB에 부하가 몰릴 가
능성이 높음
완화 방법
• 캐시 warming 스크립트 사용
• 노드 추가/삭제는 점진적으로
• TTL 값에 랜덤성 부여
• 캐시 효율적인 전략 사용
Redis 특징 요약
다양한명령어 제공
~200 commands
메모리 기반 키-값 저장소
다양한 종류의 자료구조
strings, lists, hashes, sets, sorted sets, bit
maps & HyperLogLogs
싱글 스레드 구조
원자적 연산 제공
supports transactions
has ACID properties
무진장 빠름!
<1ms latency for most commands
읽기 복제본 지원
데이터 영속성 지원
snapshots or append-only log
Pub/sub 기능 제공
18.
Amazon
ElastiCache
Multi-AZ 기능 사용가능
CloudWatch를 통한 모니터링
완전 관리형 서비스
향상된 Redis 엔진 적용
바로 시작 가능 및 손쉬운 사용
Redis 직접 운용 vs ElastiCache Redis
AZ간 데이터 전송 비용 없음
19.
PrimaryReplica
Replica
writes
Use Primary Endpoint
reads
UseRead Replicas
Auto-Failover
복제 지연이 가장 적은 복
제본이 선택됨
DNS endpoint 변화 없음
Multi-AZ 자동 Failover
ElastiCache
for Redis
ElastiCache
for Redis
ElastiCache
for Redis
Primary node 실패시 읽기 복제본으로 자동 Failover
주기적으로
스냅샷 저장
Endpoint 자동 감지가필요한 경우
• 클러스터 엔드포인트 확인
aws elasticache describe-cache-clusters
--cache-cluster-id mycluster
--show-cache-node-info
• 읽기 복제본 엔드포인트 확인
aws elasticache describe-replication-groups
--replication-group-id myredisgroup
• SNS 이벤트를 통해 노드 상태 변경 감지
• http://bit.ly/elasticache-sns
28.
목적/역할에 따라 클러스터분리
ELB App
External APIs
Reads
Writes
Leaderboards
특히, 리더보드의 경우에는
등수나 등급(골드, 실버, …)에
따라 분리하는 경우도 많음
User Profiles
Reads
캐싱을 적용하기도 쉬움– Lazy Caching
# Python
def get_user(user_id):
record = cache.get(user_id)
if record is None:
# Run a DB query
record = db.query("select * from users where id = ?", user_id)
cache.set(user_id, record)
return record
# App code
user = get_user(17)
36.
캐싱을 적용하기도 쉬움– Write-through
# Python
def save_user(user_id, values):
record = db.query("update users ... where id = ?", user_id, values)
cache.set(user_id, record)
return record
# App code
user = save_user(17, {"name": “Jeff Bezos"})
37.
TTL도 적용해보자!
def save_user(user_id,values):
record = db.query("update users ... where id = ?", user_id, values)
cache.set(user_id, record, 300) # TTL
return record
def get_user(user_id):
record = cache.get(user_id)
if record is None:
record = db.query("select * from users where id = ?", user_id)
cache.set(user_id, record, 300) # TTL
return record
# App code
save_user(17, {"name": "Nate Diddy"})
user = get_user(17)
38.
마이 프
레셔스!골룸!
• RedisSorted Sets 활용
• Uniqueness + Ordering
• 데이터 양이 아주 많은 경우
• 그룹(등급, 랭킹 범위)별로 분리
ZADD "leaderboard" 1201 "Gollum”
ZADD "leaderboard" 963 "Sauron"
ZADD "leaderboard" 1092 "Bilbo"
ZADD "leaderboard" 1383 "Frodo”
ZREVRANGE "leaderboard" 0 -1
1) "Frodo"
2) "Gollum"
3) "Bilbo"
4) "Sauron”
ZREVRANK "leaderboard" "Sauron"
(integer) 3
사용 패턴 #2 – 실시간 랭킹 보드
39.
사용 패턴 #3– PUB/SUB을 통한 메시지 전달
• Redis PUBLISH / SUBSCRIBE 기능
• 특정 그룹간 채팅으로 활용 가능
• 서버간 통신에 활용 가능
• (참고) 넥슨의 듀랑고
• 단발성 Queue로도 사용할 수 있음
SUBSCRIBE chat_channel:114
PUBLISH chat_channel:114 "Hello all"
>> ["message", "chat_channel:114", "Hello all"]
UNSUBSCRIBE chat_channel:114
40.
• 추천 엔진및 게시판 랭킹에 활용 가능
• Redis counters – 좋아요/싫어요 카운팅
• Redis hashes – 사용자들의 별점 기록
• 자카드 계수(Jaccardian similarity)를 활용하여 평균 별점 계산
https://github.com/davidcelis/recommendable
사용 패턴 #4 – 추천(별점 표시) 기능
INCR item:38927:likes
HSET item:38927:ratings "Susan" 4
INCR item:38927:dislikes
HSET item:38927:ratings "Tommy" 2
41.
• API 요청에대한 스로틀링 처리
• 게임 bot(매크로)의 burst한 요청 제한
• Redis 카운터 및 TTL 활용
ELB
Externally
Facing A
PI
Reference: http://redis.io/commands/INCR
FUNCTION LIMIT_API_CALL(APIaccesskey)
limit = HGET(APIaccesskey, “limit”)
time = CURRENT_UNIX_TIME()
keyname = APIaccesskey + ":” + time
count = GET(keyname)
IF current != NULL && count > limit THEN
ERROR ”API request limit exceeded"
ELSE
MULTI
INCR(keyname)
EXPIRE(keyname,10)
EXEC
PERFORM_API_CALL()
END
사용 패턴 #5 - Rate Limiting
Redis 운영중 주로겪는 문제
• 증상은 다양
• [Memory] 풀 나서 인스턴스 죽었어요
• [CPU] 쳐묵쳐묵 버벅버벅
• [Network] Master/Slave 연결이 자꾸 끊겨요
• 주요 원인은 간단
• Fork()를 통한 백업 및 Master/Slave 복제
• Client-Output-Buffer 스로틀링
• Failover 후 full-resync
ElastiCache용 Redis 엔진은 많은 부분을 수정해서 적용
44.
향상된 Redis 엔진
•Amazon ElastiCache에서만 사용가능
• Forkless Replication 구현
• 스냅샷 또는 복제 수행시 메모리 사용 최소화
• 메모리 용량이 충분하다면, 그냥 Fork 사용 (빠르기 때문)
• 동적으로 Client-Output-Buffer (COB) 스로틀링 제어
• 부드러운(?) Failover 지원
• PSYNC
45.
Forkless Replication
• RDB(BGSAVE): 내부적으로 자식 프로세스를 fork()해서 스냅샷 작업
• Replication: fork()된 자식 프로세스가 복제본으로 데이터를 전달
• Fork로 인한 메모리 사용이 최대 2배가 될 수 있음
• 물리 메모리 부족시 Swap 발생
• reserved-memory 파라미터를 설정해서 메모리 확보 가능
46.
Dynamic Client OutputBuffer
• Client Output Buffer
• 결과 데이터 또는 복제 데이터를 버퍼링 한 후에 Flush해서 전달
• Redis.conf에서 soft/hard limit 설정 가능
• limit 도달시 클라이언트 접속 종료
• “버퍼 크기 x 클라이언트 수(복제본 포함)” 만큼 메모리 할당
• 순식간에 메모리 수 GB를 먹어버릴 수 있음
메모리 부족으로 인한 각종 증상 (eviction, disk swap, …)
• 크기를 작게 잡으면 클라이언트가 자주 종료
재접속, 재요청, 동기화 증가로 인한 CPU 사용률 증가
• 동적 쓰기 제어
• COB에 쓰기 작업을 CPU 및 메모리 사용 상황에 따라 동적으로 제어
47.
Redis Cluster
• Redis에도드디어 (수평적 분할) 클러스터 기능 도입
• Redis 3.0의 클러스터 기능 우선 적용
• Multiple Shard!
• Redis Cluster 명령어 모두 지원 예정
• AWS 관리 콘솔 업데이트