Upload
amazon-web-services-korea
View
1.013
Download
9
Embed Size (px)
Citation preview
Amazon ElastiCache
게임 서비스를 위한 ElastiCache 활용 전략
구승모Gaming SA
AGENDA
• ElastiCache
• Memcached
• Redis
• 게임 서비스를 위한 사용 패턴
• ElastiCache 전용의 향상된 Redis 엔진
Amazon RDS
Amazon DynamoDB Amazon Redshift
Amazon ElastiCache
Compute Storage
AWS Global Infrastructure
Database
Application Services
Deployment & Administration
Networking
AWS Database Services
클라우드 상에서 동작하는 고성능의In-Memory Key-Value 저장소
AmazonRDS
Request RateHigh Low
Cost/GBHigh Low
LatencyLow High
Data VolumeLow High
AmazonGlacier
AmazonCloudSearch
Struct
ure
Low
High
AmazonDynamoDB
AmazonElastiCache
인메모리 키-값 형태의 저장소
고성능
각종 모니터링 및 알림 기능
관리형 서비스
Redis와 Memcached 지원Amazon
ElastiCache
관리형 서비스 = 자동화된 운영이 가능
EC2상에서 Redis/Memcached 직접 운영하는 경우 ElastiCache 사용하는 경우
Memcached vs Redis
• 수평적인 문자열 캐시• 멀티스레드• 디스크에 저장 안함• 단순한 관리• 수평적 확장이 쉬움
• 싱글 스레드• 원자적 연산 지원• 다양한 자료 구조 지원• Pub/Sub 기능 지원• 읽기 복제본 지원• Failover 지원
ElastiCache - Memcached
Memcached 특징 요약
내부적으로 메모리풀
메모리 기반 키-값 저장소
문자열 기반의 저장소
멀티 스레드 구조
아주 빠름!
관리의 단순함
데이터 영속성은지원 하지 않음
Sharding 지원
Sharding
Consistent Hashing
Consistent Hashing 기능이 구현된 클라이언트 제공• Ruby
• Dalli https://github.com/mperham/dalli• Plus ElastiCache https://github.com/ktheory/dalli-elasticache
• Python• HashRing / MemcacheRing https://pypi.python.org/pypi/hash_ring/• Django w/ Auto-Discovery https://github.com/gusdan/django-elasticache
• Node.js• node-memcached https://github.com/3rd-Eden/node-memcached• Auto-Discovery example http://stackoverflow.com/questions/17046661
• Java• SpyMemcached https://github.com/dustin/java-memcached-client• ElastiCache Client https://github.com/amazonwebservices/aws-elasticache-cluster-client-memcac
hed-for-java
• PHP• ElastiCache Client https://github.com/awslabs/aws-elasticache-cluster-client-memcached-for-php
• .NET• ElastiCache Client https://github.com/awslabs/elasticache-cluster-config-net
Auto-Discovery Endpoint
# 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
Thundering Herd
주요 원인• APP시작시 캐시 채우기• 노드의 추가/삭제• 캐시 키의 무효화 (TTL out)• 캐시 메모리 꽉 참
https://en.wikipedia.org/wiki/Thundering_herd_problem
캐시 미스가 순간적으로 많이 발생하면 DB에 부하가 몰릴 가능성이 높음
완화 방법• 캐시 warming 스크립트 사용• 노드 추가/삭제는 점진적으로• TTL 값에 랜덤성 부여• 캐시 효율적인 전략 사용
ElastiCache - Redis
Redis 특징 요약
다양한 명령어 제공~200 commands
메모리 기반 키-값 저장소
다양한 종류의 자료구조strings, lists, hashes, sets, sorted sets, bitmaps & HyperLogLogs
싱글 스레드 구조
원자적 연산 제공supports transactionshas ACID properties
무진장 빠름!<1ms latency for most commands
읽기 복제본 지원
데이터 영속성 지원snapshots or append-only log
Pub/sub 기능 제공
Amazon ElastiCache
Multi-AZ 기능 사용 가능
CloudWatch를 통한 모니터링
완전 관리형 서비스
향상된 Redis 엔진 적용
바로 시작 가능 및 손쉬운 사용
Redis 직접 운용 vs ElastiCache Redis
AZ간 데이터 전송 비용 없음
Prim
ary
Replic
a
Replic
a
writesUse Primary Endpoint
reads
Use Read Replicas
Auto-Failover
복제 지연이 가장 적은 복제본이 선택됨
DNS endpoint 변화 없음
Multi-AZ 자동 Failover
ElastiCache for Redis
ElastiCache for Redis
ElastiCache for Redis
Primary node 실패시 읽기 복제본으로 자동 Failover
주기적으로스냅샷 저장
Multi-AZ 자동 Failover 과정
Multi-AZ 자동 Failover 과정
Multi-AZ 자동 Failover 과정
Multi-AZ 자동 Failover 과정
일반적인 사용 구조
ELB App
External APIs
Replication Group
ReadsWrites
Redis 읽기/쓰기용 연결 구성
# Ruby example
redis_write = Redis.new(
'mygame-dev.z2vq55.ng.0001.usw2.cache.amazonaws.com')
redis_read = Redis::Distributed.new([
'mygame-dev-002.z2vq55.ng.0001.usw2.cache.amazonaws.com',
'mygame-dev-003.z2vq55.ng.0001.usw2.cache.amazonaws.com'
])
redis_write.zset("leaderboard", “player_aa", 1997)
top_10 = redis_read.zrevrange("leaderboard", 0, 10)
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
목적/역할에 따라 클러스터 분리
ELB App
External APIs
ReadsWrites
Leaderboards
특히, 리더보드의 경우에는등수나 등급(골드, 실버, …)에따라 분리하는 경우도 많음
User Profiles
Reads
Alarms
CloudWatch를 통한 모니터링
• 콘솔에서 쉽게 확인 가능
• 노드별 상태 확인 가능
• 특정 조건으로 알람 설정• CPU/MEM 제한에 근접
주요 CloudWatch Metrics
바람직한(?) 상황 지표는
• CPUUtilization• Memcached – 90% 까지는 괜찮음
• Redis – 코어 수를 고려해야 함 (예: 90% / 4 = 22.5%)
• SwapUsage low
• Evictions low
• CacheMisses / CacheHits Ratio low
• Current Connections stable
주요 리소스 사용률이 높다면…
Scale-up을 고려
1. 스냅샷을 Amazon S3에 저장http://bit.ly/redis-snapshot
2. 스냅샷으로부터 클러스터 생성http://bit.ly/redis-seeding
3. 스케일업 완료!
게임 서비스를 위한 사용 패턴
사용 패턴 #1 - 캐싱
Elastic LoadBalancing
EC2 App Instances
RDS MySQL DB Instance
ElastiCache
Database Writes
App Reads
ClientsCacheUpdates
Database Reads
1. DB에 걸리는 부하를 offloading 시키는 용도
2. DBMS와 별개로 임시 키-값 저장소로 활용도 가능(예: web session management)
Amazon ElastiCache
예측 가능한 성능
DB 부하 분산
읽기 Throughput 증가
애플리케이션 지연 감소
캐싱이 가져다 주는 이점
궁극적으로 DB 비용 감소
캐싱을 적용하기도 쉬움 – 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)
캐싱을 적용하기도 쉬움 – 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"})
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)
마이 프레셔스!골룸!
• Redis Sorted 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 – 실시간 랭킹 보드
사용 패턴 #3 – PUB/SUB을 통한 메시지 전달
• Redis PUBLISH / SUBSCRIBE 기능
• 특정 그룹간 채팅으로 활용 가능
• 서버간 통신에 활용 가능• (참고) 넥슨의 듀랑고
• 단발성 Queue로도 사용할 수 있음
SUBSCRIBE chat_channel:114PUBLISH chat_channel:114 "Hello all">> ["message", "chat_channel:114", "Hello all"]UNSUBSCRIBE chat_channel:114
• 추천 엔진 및 게시판 랭킹에 활용 가능• Redis counters – 좋아요/싫어요 카운팅
• Redis hashes – 사용자들의 별점 기록
• 자카드 계수(Jaccardian similarity)를 활용하여 평균 별점 계산https://github.com/davidcelis/recommendable
사용 패턴 #4 – 추천(별점 표시) 기능
INCR item:38927:likesHSET item:38927:ratings "Susan" 4
INCR item:38927:dislikesHSET item:38927:ratings "Tommy" 2
• 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 + ":” + timecount = GET(keyname)IF current != NULL && count > limit THEN
ERROR ”API request limit exceeded"ELSE
MULTIINCR(keyname)EXPIRE(keyname,10)
EXECPERFORM_API_CALL()
END
사용 패턴 #5 - Rate Limiting
ElastiCache 전용의 향상된 Redis 엔진
Redis 운영중 주로 겪는 문제
• 증상은 다양• [Memory] 풀 나서 인스턴스 죽었어요
• [CPU] 쳐묵쳐묵 버벅버벅
• [Network] Master/Slave 연결이 자꾸 끊겨요
• 주요 원인은 간단• Fork()를 통한 백업 및 Master/Slave 복제
• Client-Output-Buffer 스로틀링
• Failover 후 full-resync
ElastiCache용 Redis 엔진은 많은 부분을 수정해서 적용
향상된 Redis 엔진
• Amazon ElastiCache에서만 사용가능
• Forkless Replication 구현• 스냅샷 또는 복제 수행시 메모리 사용 최소화
• 메모리 용량이 충분하다면, 그냥 Fork 사용 (빠르기 때문)
• 동적으로 Client-Output-Buffer (COB) 스로틀링 제어
• 부드러운(?) Failover 지원• PSYNC
Forkless Replication
• RDB (BGSAVE): 내부적으로 자식 프로세스를 fork()해서 스냅샷 작업
• Replication: fork()된 자식 프로세스가 복제본으로 데이터를 전달
• Fork로 인한 메모리 사용이 최대 2배가 될 수 있음• 물리 메모리 부족시 Swap 발생
• reserved-memory 파라미터를 설정해서 메모리 확보 가능
Dynamic Client Output Buffer
• Client Output Buffer• 결과 데이터 또는 복제 데이터를 버퍼링 한 후에 Flush해서 전달
• Redis.conf에서 soft/hard limit 설정 가능• limit 도달시 클라이언트 접속 종료
• “버퍼 크기 x 클라이언트 수(복제본 포함)” 만큼 메모리 할당• 순식간에 메모리 수 GB를 먹어버릴 수 있음
메모리 부족으로 인한 각종 증상 (eviction, disk swap, …)
• 크기를 작게 잡으면 클라이언트가 자주 종료 재접속, 재요청, 동기화 증가로 인한 CPU 사용률 증가
• 동적 쓰기 제어• COB에 쓰기 작업을 CPU 및 메모리 사용 상황에 따라 동적으로 제어
Redis Cluster
• Redis에도 드디어 (수평적 분할) 클러스터 기능 도입• Redis 3.0의 클러스터 기능 우선 적용
• Multiple Shard!
• Redis Cluster 명령어 모두 지원 예정
• AWS 관리 콘솔 업데이트
마무으리
• ElastiCache• In-memory 저장소를 클라우드 상에서 손쉽고 안전하게 운용
• Memcached & Redis
• 게임 서비스를 위한 유용한 패턴
• 향상된 전용 Redis엔진
감사합니다.