Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

week06_junsik #32

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions redis/week06/junsik/persistence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
- 지속성은 SSD(Solid State Disk)와 같은 `내구성 있는 스토리지에 데이터를 쓰는 것을 의미`
- `RDB` (Redis 데이터베이스): RDB 지속성은 지정된 간격으로 데이터 세트의 특정 시점 스냅샷을 수행
- `AOF` (Append Only File): AOF 지속성은 서버에서 수신한 모든 쓰기 작업을 기록. 그런 다음 서버 시작 시 이러한 작업을 다시 재생하여 원래 데이터 세트를 재구성. 명령은 Redis 프로토콜 자체와 동일한 형식을 사용하여 기록
- `No persistence` : 지속성을 완전히 비활성화. 캐싱할 때 가끔 사용
- `RDB + AOF` : 동일한 인스턴스에서 AOF와 RDB를 결합

# RDB 장점
- RDB 파일은 `백업에 적합`. 예를 들어, 최근 24시간 동안 매시간 RDB 파일을 보관하고 30일 동안 매일 RDB 스냅샷을 저장할 수 있음. 이를 통해 재해 발생 시 `다양한 버전의 데이터 세트를 쉽게 복원 가능`
- RDB는 원거리 데이터 센터나 Amazon S3(암호화 가능)로 전송할 수 있는 단일 압축 파일이므로 재해 복구에 매우 용이
- Redis 상위 프로세스가 지속하기 위해 수행해야 하는 유일한 작업은 나머지 모든 작업을 수행할 하위 프로세스를 포크하는 것이므로 RDB는 Redis 성능을 극대화. 상위 프로세스는 디스크 I/O 등을 수행하지 않음
- RDB는 AOF에 비해 대규모 데이터 세트로 더 빠르게 다시 시작 가능
- 복제본에서 RDB는 재시작 및 장애 조치 후 부분 재동기화 지원

# RDB 단점
- 일반적으로 RDB 스냅샷은 5분 이상마다 생성되므로 어떤 이유로든 Redis가 올바른 종료 없이 작동을 중지하는 경우 `최신 데이터가 손실될 수 있음`
- RDB는 하위 프로세스를 사용하여 디스크에 지속되기 위해 자주 fork()해야 합니다. 포크()는 데이터 세트가 큰 경우 시간이 많이 걸릴 수 있으며, 데이터 세트가 매우 크고 CPU 성능이 좋지 않은 경우 Redis가 몇 밀리초 동안 또는 심지어 1초 동안 클라이언트 서비스 제공을 중지할 수도 있음

# AOF 장점
- AOF를 사용하면 Redis가 훨씬 더 `안정적`
- 다양한 fsync 정책을 설정할 수 있음
- fsync는 백그라운드 스레드를 사용하여 수행되며, 메인 스레드는 fsync가 진행 중이지 않을 때 쓰기를 수행하려고 시도하므로, `최대 1초 분량의 쓰기만 손실될 수 있음`
- AOF 로그는 추가 전용 로그이므로, 전원 중단이 발생해도 탐색이나 손상 문제가 없음
- 어떤 이유로 로그가 반쯤 작성된 명령어로 끝나더라도 (디스크가 가득 차거나 기타 이유로) redis-check-aof 도구를 사용하여 쉽게 수정 가능
- Redis는 AOF가 너무 커지면 백그라운드에서 자동으로 AOF를 다시 작성할 수 있음. 다시 작성하는 과정은 완전히 안전

# AOF 단점
- AOF 파일은 일반적으로 동일한 데이터 세트에 대해 `RBD 파일보다 크기가 큼`
- 정확한 fsync 정책에 따라 AOF는 RDB보다 느릴 수 있음

# 그래서 어떤 걸 사용하는게 좋을까?
- 데이터 안전성에 있어 `PostgreSQL이 제공할 수 있는 수준에 가까운 것`을 원한다면, `두 가지 지속성 방법을 모두 사용하는 것이 일반적`인 지침
- 데이터를 매우 중요하게 생각하지만, 재난 발생 시 몇 분간의 데이터 손실은 감수할 수 있다면, 단독으로 RDB만 사용해도 ok
- `AOF만을 사용`하는 많은 사용자들이 있지만, 데이터베이스 백업을 위해, 더 빠른 재시작을 위해, 그리고 AOF 엔진의 버그 발생 시를 대비하여 가끔씩 RDB 스냅샷을 가지는 것이 좋은 아이디어이므로, `권장하지 않음`

# 스냅샷
- 기본적으로 Redis는 `데이터 세트의 스냅샷을 dump.rdb라는 이진 파일로 디스크에 저장`
- 데이터 세트에서 최소 M개의 변경이 있을 경우 N초마다 데이터 세트를 저장하도록 Redis를 구성할 수 있으며, SAVE 또는 BGSAVE 명령을 수동으로 호출 가능
- ## 작동원리
- Redis 포크. 이제 부모 프로세스와 자식 프로세스 존재
- 자식 프로세스가 임시 RDB 파일에 데이터 세트를 쓰기 시작
- 자식 프로세스가 새 RDB 파일 작성을 마치면, 이 파일이 이전 파일을 대체

# AOF
- ## Log rewriting
- Rewriting 은 `완전히 안전`. Redis가 이전 파일에 계속 추가하는 동안, 현재 데이터 세트를 생성하는 데 필요한 최소한의 작업 세트로 완전히 새로운 파일이 생성되며, 이 두 번째 파일이 준비되면 Redis는 두 파일을 교체하고 새 파일에 추가하기 시작

- ## How durable is the append only file?
- appendfsync `always`: AOF에 새 명령이 추가될 때마다 fsync를 수행. `매우 느리지만 매우 안전`. 명령어들은 여러 클라이언트의 일련의 명령이나 파이프라인이 실행된 후 AOF에 추가되므로, 이는 단일 쓰기와 단일 fsync를 의미
- appendfsync `everysec`: 매초 fsync를 수행. 충분히 빠르며(버전 2.4부터 스냅샷 방식만큼 빠를 가능성이 높음), 재난이 발생하면 1초 분량의 데이터를 잃을 수 있음
- appendfsync `no`: fsync를 전혀 수행하지 않고, 데이터를 운영 체제에 맡김. `가장 빠르지만 가장 안전하지 않은 방법`. 커널의 튜닝에 달려 있음
- 권장되고 기본적으로 설정된 정책은 `매초 fsync를 수행`. 이는 빠르면서도 상대적으로 안전. always 정책은 실제로 매우 느리지만, 그룹 커밋을 지원하므로 Redis는 여러 병렬 쓰기가 있을 경우 단일 fsync 작업을 수행하려고 시도

- ## What should I do if my AOF gets truncated?
- Redis의 최신 주요 버전들은 어쨌든 AOF를 로드할 수 있으며, `파일에서 마지막으로 형식에 맞지 않는 명령어를 단순히 무시`
- 기본 구성을 변경하여 이러한 경우에 Redis가 중단되도록 강제할 수 있지만, 파일의 마지막 명령어가 형식에 맞지 않더라도 재시작 후 가용성을 보장하기 위함

- ## What should I do if my AOF gets corrupted?
- AOF 파일이 단순히 잘린 것이 아니라, 중간에 유효하지 않은 바이트 시퀀스로 인해 손상된 경우, 상황은 더 복잡. Redis는 시작 시 이를 감지하고 중단
- 가장 좋은 방법은 `redis-check-aof 유틸리티를 실행`하는 것. 처음에는 --fix 옵션 없이 실행한 다음 문제를 이해하고, 파일에서 지정된 오프셋으로 이동하여 파일을 수동으로 수리할 수 있는지 확인. AOF는 Redis 프로토콜과 동일한 형식을 사용하므로 수동으로 수정하기가 비교적 간단. 그렇지 않은 경우 유틸리티를 사용하여 파일을 수정할 수 있지만, 그 경우에는 손상된 부분부터 파일 끝까지의 모든 AOF 부분이 버려질 수 있으며, 손상이 파일의 초기 부분에서 발생했다면 대량의 데이터 손실로 이어질 수 있음

- ## 작동원리
- Redis >= 7.0
- Redis 포크
- 자식 프로세스가 임시 파일에 새로운 기본 AOF를 작성하기 시작
- 부모 프로세스는 `새로운 증분 AOF 파일을 열어 업데이트를 계속 작성`. 다시 작성이 실패하더라도, 기존의 기본 및 증분 파일(있는 경우)과 이 새로 열린 증분 파일은 완전히 업데이트된 데이터 세트를 나타내므로 안전
- 자식 프로세스가 기본 파일의 다시 작성을 마치면, 부모 프로세스는 신호를 받고, 새로 열린 증분 파일과 자식 프로세스가 생성한 기본 파일을 사용하여 임시 매니페스트를 구축하고 영구적으로 저장
- 이제 Redis는 매니페스트 파일을 원자적으로 교체하여 이 AOF rewriting 의 결과가 적용. Redis는 또한 오래된 기본 파일과 사용되지 않는 증분 파일을 정리

- Redis < 7.0
- Redis 포크
- 자식 프로세스가 임시 파일에 새로운 기본 AOF를 작성하기 시작
- 부모 프로세스는 `모든 새로운 변경 사항을 메모리 버퍼에 누적`. 하지만 동시에 이전 추가 전용 파일에 새로운 변경 사항을 작성하므로, 다시 작성이 실패해도 안전
- 자식 프로세스가 파일의 다시 작성을 마치면, 부모 프로세스는 신호를 받고, 자식 프로세스가 생성한 파일 끝에 메모리 버퍼를 추가
- 이제 Redis는 새 파일을 이전 파일로 원자적으로 이름을 변경하고, 새 파일에 새로운 데이터를 추가하기 시작

- ## How I can switch to AOF, if I'm currently using dump.rdb snapshots?
- RDB 스냅샷을 사용 중인 서버에서 AOF를 활성화하려면, 라이브 서버에서 CONFIG 명령을 통해 AOF를 활성화하여 데이터를 변환해야 함
- 중요: 이 절차를 따르지 않고 (예: 설정만 변경하고 서버를 재시작하는 경우) 데이터 손실이 발생할 수 있음

- ## Interactions between AOF and RDB persistence
- Redis >= 2.4는 RDB 스냅샷 작업이 이미 진행 중일 때 AOF 다시 작성을 트리거하지 않도록 하며, AOF 다시 작성이 진행 중일 때 BGSAVE를 허용하지 않음. 이는 `두 Redis 백그라운드 프로세스가 동시에 무거운 디스크 I/O를 수행하는 것을 방지`

- ## Backing up Redis data
- 서버에 크론 작업을 생성하여 한 디렉토리에 시간별 RDB 파일 스냅샷을 만들고, 다른 디렉토리에 일일 스냅샷 생성
- 크론 스크립트가 실행될 때마다 find 명령을 호출하여 너무 오래된 스냅샷이 삭제되는지 확인. 예를 들어, 최근 48시간 동안의 시간별 스냅샷과 한두 달 동안의 일일 스냅샷을 취할 수 있음. 스냅샷에 날짜와 시간 정보를 포함하여 이름을 지정
- 하루에 최소 한 번은 `데이터 센터 밖으로`, 또는 적어도 Redis 인스턴스를 실행하는 물리적 기계 밖으로 RDB 스냅샷을 전송하는 것을 확실히 할 것

- ## Backing up AOF persistence
- automatic rewrites `비활성화`
- 현재 rewriting 이 진행 중인지 확인
- 여기서 aof_rewrite_in_progress가 0인지 확인. 1이면 다시 작성이 완료될 때까지 대기
- 이제 appenddirname 디렉토리의 파일들을 안전하게 복사할 수 있음
- 완료되면 다시 작성을 다시 활성화

- ## Disaster recovery
- Amazon S3 및 유사 서비스: Amazon S3와 같은 서비스는 재난 복구 시스템을 구현하는 좋은 방법. 매일 또는 매시간 RDB 스냅샷을 암호화된 형태로 S3로 전송
- SCP를 사용한 스냅샷 전송: SCP(SSH의 일부)를 사용하여 먼 서버로 스냅샷을 전송하는 것은 간단하고 안전한 방법
59 changes: 59 additions & 0 deletions redis/week06/junsik/scale_with_redis_cluster.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
- Redis는 Redis Cluster 라는 배포 토폴로지를 통해 수평적으로 확장

# Redis Cluster 101
- 데이터 세트를 `여러 노드에 자동으로 분할`
- 노드의 하위 집합에 오류가 발생하거나 클러스터의 나머지 부분과 통신할 수 없는 경우에도 작업 지속

- ## Redis 클러스터 TCP 포트
- 모든 Redis 클러스터 노드에는 `두 개의 개방형 TCP 연결이 필요`
- Redis TCP 포트, 클러스터 버스 포트
- `클러스터 버스`는 바이너리 프로토콜을 사용하는 노드 간 통신 채널, 대역폭과 처리 시간이 적기 때문에 `노드 간 정보 교환에 더 적합`
- `클라이언트`는 클러스터 버스 포트와 통신을 시도해서는 안 되며 대신 `Redis 명령 포트를 사용해야 함`

- ## Redis 클러스터 및 Docker
- 현재 Redis 클러스터는 NAT 환경이나 IP 주소나 TCP 포트가 재매핑되는 환경을 지원하지 않음
- Docker는 포트 매핑이라는 기술을 사용. Docker 컨테이너 내부에서 실행되는 프로그램은 프로그램이 사용하고 있다고 생각하는 포트와 다른 포트로 노출될 수 있음. 이는 동일한 서버에서 동일한 포트를 사용하는 여러 컨테이너를 동시에 실행하는 데 유용
- Docker를 Redis 클러스터와 호환되게 하려면, Docker의 호스트 네트워킹 모드를 사용해야 함

- ## Redis 클러스터 데이터 샤딩
- Redis 클러스터는 일관된 해싱을 사용하지 않지만 모든 키가 개념적으로 해시 슬롯 이라고 부르는 것의 일부인 다른 형태의 샤딩을 사용
- Redis 클러스터에는 16384개의 해시 슬롯 존재
- 키 모듈로 16384의 CRC16을 사용
- 키의 {} 대괄호 사이에 하위 문자열이 있는 경우 문자열 내부에 있는 내용만 해시
```
user:{123}:profile 과 user:{123}:account 는 동일한 해시 태그를 공유하므로 동일한 해시 슬롯에 있음이 보장
```

- ## Redis 클러스터 마스터-복제본 모델
- 마스터 노드의 하위 집합에 장애가 발생하거나 대부분의 노드와 통신할 수 없는 경우에도 계속 사용할 수 있도록 Redis 클러스터는 모든 해시 슬롯에 1개(마스터 자체)부터 N개의 복제본(N-1)이 있는 마스터-복제본 모델을 사용

- ## Redis 클러스터 일관성 보장
- Redis 클러스터는 `강력한 일관성을 보장하지 않음`
- 기본적으로 `비동기 복제 사용`
```
클라이언트가 마스터 B에 씀
마스터 B는 고객에게 OK라고 응답
마스터 B는 복제본 B1, B2 및 B3에 쓰기 전파

B는 클라이언트에 응답하기 전에 B1, B2, B3의 승인을 기다리지 않음
```
- Redis 클러스터는 꼭 필요한 경우 명령을 통해 구현되는 동기식 쓰기를 지원하지만, 동기식이어도 일관성 보장 안됨

# Redis Cluster configuration parameters
- Cluster-enabled`<yes/no>`
- Redis 클러스터 활성화
- Cluster-config-file`<filename>`
- Redis 클러스터 노드가 변경될 때마다 자동으로 클러스터 구성(기본적으로 상태)을 유지하는 파일
- Cluster-node-timeout`<milliseconds>`
- 지정된 시간 이상 마스터 노드에 연결할 수 없으면 해당 복제본에 의해 장애 조치
- Cluster-slave-validity-factor`<factor>`
- 0 으로 설정되면 복제본은 항상 자신이 유효한 것으로 간주하므로 마스터와 복제본 사이의 링크가 연결 해제된 시간에 관계없이 항상 마스터 장애 조치를 시도
- 노드 시간 초과가 5초로 설정되고 유효성 계수가 10으로 설정된 경우 50초 이상 마스터에서 연결이 끊어진 복제본은 마스터 장애 조치를 시도하지 않음
- Cluster-migration-barrier`<count>`
- 마스터가 다른 복제본이 더 이상 어떤 복제본에도 포함되지 않는 마스터로 이동할 수 있도록 연결을 유지할 최소 복제본 수
- Cluster-require-full-coverage`<yes/no>`
- `yes` 로 설정되어 있으면, 키 공간의 일부가 어떤 노드에도 포함되지 않는 경우 클러스터는 쓰기 작업을 수락하지 않음
- `no` 로 설정된 경우, 클러스터는 키의 일부분에 대한 요청만 처리할 수 있더라도 여전히 쿼리를 처리
- Cluster-allow-reads-when-down`<yes/no>`
- `yes` 로 설정하면 실패 상태 동안 노드에서 읽기를 허용
- `no` 로 설정되면 Redis 클러스터의 노드는 클러스터가 실패로 표시되거나 노드가 도달할 수 없을 때 모든 트래픽 제공을 중지