Redis trouble shooting

48
인프라 운영자를 위한 Redis 트러블 슈팅 Clark.kang [email protected]

Transcript of Redis trouble shooting

Page 1: Redis trouble shooting

인프라 운영자를 위한 Redis 트러블 슈팅

Clark.kang [email protected]

Page 2: Redis trouble shooting

목차

• Redis 특성 소개

– Single Threaded

• 장애 사례 및 대응법

– G 서비스 장애 사례

– P 서비스 장애 사례

– S 서비스 장애 사례

• Redis 보안 이슈

Page 3: Redis trouble shooting

Single Threaded #1

Client #1

Client #2

……

Client #N

Redis Event Loop

I/O Multiplexing

Process Command

Packet #1

Packet #2

Page 4: Redis trouble shooting

Single Threaded #2

• 한 번에 하나의 명령만 처리 됨.

• 긴 작업을 호출하면 Redis 의 다른 명령들은 전부 Pending 됨

– Keys, flushall, flushdb, lua script, MULTI/EXEC

• 내부적으로 다른 스레드가 있긴 하지만 fsync 용임.

Page 5: Redis trouble shooting

얼마나 느린가?

Command Item Count Time

flashall 1,000,000 1000ms(1 second)

Page 6: Redis trouble shooting

추천 버전 #1

• 가능한 최신 버전

– 3.0.x 도 괜찮음.

– 아니면 2.8.x 후반대(최소 2.8.13 이후가 유리)

• 버전마다 약간씩의 차이가 있음.(최신 버전이 젤 좋음)

– 2.6.x 에서는 config set client-output-buffer-limit 은 redis-cli 에서만 가능

– 2.8.20에서는 config set client-output-buffer-limit 에서 1GB 이런 표현이 안됨

Page 7: Redis trouble shooting

메모리 파편화 #1

• Jemalloc 이 3.6.0 이전 버전

Page 8: Redis trouble shooting

메모리 파편화 #2

• Jemalloc 이 3.6.0 이후버전

– 그래도 주의가 필요.

Page 9: Redis trouble shooting

추천 클라이언트(매니지먼트용)

• Redis-cli 를 쓰세요.

– 권장 추천

• telnet 도 가능

– Inline command 라고 해서 한줄짜리는 레디스가 알아서 해석

– Inline command는 twemproxy에서는 지원되지 않음

– 구버전의 경우는 안먹는 커맨드가 있을 수도 있음

Page 10: Redis trouble shooting

서비스 팀에 제공시 유의 사항

• 캐시인지 저장용인지에 대해서 확인이 필요

– 캐시용이라면, SAVE 옵션은 무조건 끄고 주어야 합니다.

– 저장용일때도, 해당 옵션에 대한 조절이 필요합니다.

• 하나의 레디스 인스턴스가 전체 메모리를 사용하는 것 보다는 적절히 여러 개의 인스턴스를 띄우도록 가이드합니다.

– 16G 면 11G, 12G를 쓰는것보다는 6G * 2 로 사용하는게 더 좋음.

• 기본적으로 maxmemory를 설정해 두는 것이 유리.

Page 11: Redis trouble shooting

서비스 팀에 제공시 유의 사항

• CPU 4 core 32G Memory

Mem: 26G

Mem: 8G

Mem: 8G

Mem: 8G

Page 12: Redis trouble shooting

Replication

Page 13: Redis trouble shooting

Redis Replication

• Redis는 Single Thread

– Replication을 위해서 fork를 하게 됨

• Chained replication을 지원

– Multi-Master 또는 양방향 Replication은 지원 안함

• Replication을 해야할 상황이 발생할 수 있으므로 메모리에 신경써야 함.

Page 14: Redis trouble shooting

Replication •Support Chained Replication

Master 1st Slave 2nd Slave

1st slave is master of 2nd slave

Page 15: Redis trouble shooting

Replication

Master Slave replicationCron

Health check

Page 16: Redis trouble shooting

Replication

Master Slave replicationCron

Health check

Page 17: Redis trouble shooting

Replication

Master Slave replicationCron

When master reruns, Resync with Master

Page 18: Redis trouble shooting

Mistake: Replication

Master Slave replicationCron

Slave will has no data after resyncing

If master has no data.

Page 19: Redis trouble shooting

Persistent

Page 20: Redis trouble shooting

Persistent 라고 쓰고 Hell Gate라고 읽으세요.

Page 21: Redis trouble shooting

RDB/AOF

• RDB/AOF는 완전히 별개의 기능(서로 연관성이 없음)

• RDB – 현재 프로세스를 Fork 해서 현재의 메모리 상태를 디스크로 덤프함.

– COW에 의해서 읽기가 많을 때는 추가로 사용하는 메모리가 적지만, write 가 많으면 최대 메모리 2배까지 사용 가능.

• AOF – 현재 레디스의 write 커맨드를 디스크에 저장함.

– Disk Sync 옵션에 따라서 성능에 영향을 줌(default: everysec)

– AOF rewrite가 일어나기 전까지는 그래도 부하가 적음.

Page 22: Redis trouble shooting

피해가고 싶어도 무조건 겪게 됩니다. (장비 이전 이슈…)

Page 23: Redis trouble shooting

Migration

Page 24: Redis trouble shooting

Migration 방법

1. 현재 장비에 대해서 대체 장비를 준비

2. 대체 장비에서 slave of 현재장비 IP 현재장비 port

3. Replication 완료를 기다림 1. 이때 무조건 fork 가 발생(메모리 두배 이슈 발생 가능)

4. Replication이 끝나면 Slave 장비에서 쓰기 활성화 1. Config set slave-read-only no

5. 클라이언트들이 대체 장비를 바라보도록 설정

6. 대체 장비에서 다음 명령 수행 1. slaveof no one

Page 25: Redis trouble shooting

Partial Sync

Page 26: Redis trouble shooting

Redis Replication 과정

1. Slave 가 Master로 Sync 명령을 보냄

2. Master는 Fork 하여 RDB 생성

3. RDB 생성이 끝나면 Master는 RDB를 Slave로 전송

4. 해당 시간동에 master가 받는 명령어는 memory에 저장

5. RDB 전송이 끝나면 Slave 가 해당 RDB Load

6. Slave의 RDB 로드가 끝나면 Master가 메모리에 쌓인 데이터 전송

Page 27: Redis trouble shooting

Redis Repliaction의 문제점

• Redis의 경우 마스터 슬레이브 상황에서 Master랑 연결이 잠시라도 끊어지면, Slave는 Master의 모든 내용을 Full Sync 받는다.

– Disk IO는 비쌈

• Slave는 Master 상태를 계속 폴링으로 체크함.

Page 28: Redis trouble shooting

Partial Sync

• Master와의 접속이 끊기고 다시 연결될 때, 기존과 동일한 master 라면, 그리고 master의 memory buffer 범위 내로 데이터가 변경되었다면 해당 데이터만 전송 받아서 full sync를 피함.

– 데이터 변경이 없어도, 시간이 지나면 PING 등의 메시지로 인해서 버퍼가 찰 수 있다는게 함정.

• 다만 마스터가 바뀌는 경우에는 Partial Sync는 안됨

– 즉, 장애로 마스터 장비 위치가 바뀌면… slave는 무조건 full sync

Page 29: Redis trouble shooting

장애 사례

Page 30: Redis trouble shooting

T모 서비스

• 상황 – 캐시로만 사용

• Redis 설정 – stop-writes-on-bgsave-error yes

• 장애 현상 – RDB 생성 실패 후, write 가 계속 실패. – 읽기만 가능

• 장애 처리 – stop-writes-on-bgsave-error no 로 설정 – 해당 값이 yes 면 RDB 생성에 실패하면 write 명령을 모두 에러냄.

Page 31: Redis trouble shooting

G모 서비스

• 상황 – 캐시로만 사용

• Redis 설정 – SAVE 가 디폴트 옵션 – SAVE 900 1 – SAVE 300 10 – SAVE 60 10000

• 장애 현상 – 짧은 시간에 계속 RDB가 생성되면서 Disk IO가 많이 발생

• 장애 처리 – SAVE 값을 제거(config set SAVE “”)

Page 32: Redis trouble shooting

S모 서비스

• 상황 – 캐시와 일부 복구가 필요한 데이터.

– 물리메모리 32G 에서 28G 사용

– 디스크 장애도 있던 상황

• 장애 현상 – Swap memory 사용으로 응답시간이 늘어남.

– RDB 생성에 엄청난 시간이 걸림(28G 메모리 dump에 7시간 이상 걸림)

• 장애 처리 – 그냥 포기(T.T)

Page 33: Redis trouble shooting

Copy on Write

• 부모 프로세스의 메모리 Page 에 Write 가 발생할 때 마다, 해당 메모리 Page를 복사하게 된다.

• 읽기의 경우에는 메모리를 추가로 복사할 필요가 없다.

Page 34: Redis trouble shooting

Copy on Write #1

Process - Parent

Physical Memory

Page A

Page B

Page C

Page 35: Redis trouble shooting

Copy on Write #2 – Fork(), 메모리 수정 전

Process - Parent

Physical Memory

Page A

Page B

Page C

Process - Child

Page 36: Redis trouble shooting

Copy on Write #2 – Fork(), 메모리 수정 후

Process - Parent

Physical Memory

Page A

Page B

Page C

Copy of Page C

Process - Child

Page 37: Redis trouble shooting

Copy on Write 결론

• 최악의 경우에는 메모리를 두 배 까지 사용할 수 있다.

– 모든 Page 에 write가 발생했을 경우

• 메모리가 부족해서 스왑 영역을 사용하면 엄청나게 느려지게 된다.

Page 38: Redis trouble shooting

P모 서비스(#1)

• 상황

– AOF 사용

– 8개의 인스턴스가 256G 장비에서 동작

• 장애 현상

– 8개의 AOF가 전부 AOF Rewrite가 발생

– 과도한 메모리 사용과 Disk 사용으로 인한 장애

• 장애 처리

– AOF Rewrite를 중지

Page 39: Redis trouble shooting

P모 서비스(#2) – 장애는 아님

• 상황

– 네트웍 Master/Slave Replication이 모두 끊어짐.

• 장애 가능성

– 네트웍이 복구되면 모든 서버가 Master/Slave 상태를 복구하게 됨

– 모든 Master가 Fork 하여 메모리와 Disk를 사용할 가능성(전면장애)

• 대처

– Slaveof no one 명령을 이용하여 모든 M/S 관계를 제거

– 순차적으로 한대씩 Replication을 재 연결함.

Page 40: Redis trouble shooting

Replication 실패

• 상황 – 메모리 사용량이 20G 정도 – 어느정도의 Write가 발생하는 경우

• 장애 현상 – Master/Slave Replication 연결이 계속 실패함

• 장애 처리 #1 – Redis는 Replication 중에 fork 후에 들어오는 데이터를 저장함. – 해당 값이 특정 메모리 사이즈를 넘어가면 접속이 끊어짐 – client-output-buffer-limit slave 256mb 64mb 60 – 20G 이상이면 이 값을 512mb 이상으로 잡아두는 것이 좋음(메모리 사이즈에 비례)

• 데이터가 굉장히 많으면 미리 슬레이브의 데이터를 지워주는 것이 유리함. – Loading 직전에, 데이터를 지우므로, 지우는데도 시간이 많이 걸릴 수 있음.

Page 41: Redis trouble shooting

THP Disable

• 상황

– THP가 enable

– 메모리 사용량이 많음

• 장애 현상

– Fork 시에 메모리 사용량에 따라서 fork 시간이 오래 걸림

• 장애 처리

– THP Disable

Page 42: Redis trouble shooting

Diskless Replication

• RDB 덤프를 디스크에 저장하면 disk io가 발생하므로, 디스크에 쓰지 않고, 바로 Slave로 전송

– AWS의 EBS는 느리다.

– 일반 서버의 디스크도 많이 쓰면 느리다.

• 메모리 두배 이슈를 해결하지는 못하지만, Disk IO는 줄일 수 있음.

Page 43: Redis trouble shooting

Redis 모니터링

Page 44: Redis trouble shooting

Redis Monitoring 항목

항목 수집 위치(Host or Redis(info))

CPU Usage, Load Host

Network inbound, outbound

Host

현재 클라이언트 개수, max client 설정

Redis

키 개수, 명령어 처리 수 Redis

메모리 사용량, RSS Redis

Disk 사용량, io Host

Expired keys, Evicted keys Redis

Page 45: Redis trouble shooting

Redis 보안 이슈

Page 46: Redis trouble shooting

Redis 보안은 굉장히 취약하다.

• ACL

– 기능 없음

– 내부망이 아닐 경우 절대로 해당 포트가 열려있으면 안됨

– Root로 띄우는 경우가 많은데, 가능한 특정 user로 띄워야 함

• 데이터

– 평문으로 모두 확인 가능.

Page 47: Redis trouble shooting

Redis 해킹 사례

• 해당 포트가 외부에 열려있음(자세한 코드는 숨깁니다.)

– Config set dir “/root/.ssh”

– Config set dbfilename “authorized_keys”

– Save

• 이제 루트로 접근 가능.

Page 48: Redis trouble shooting

감사합니다.