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_taeyeon #31

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
92 changes: 92 additions & 0 deletions redis/week06/taeyeon/Persisence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
Redis 데이터를 disk에 쓰는 방법(영속성)
> https://redis.io/docs/management/persistence/

Redis는 데이터를 영구적인 저장소(예: SSD)에 기록하는 여러 가지 영속성 옵션을 제공한다.
`RDB(Redis Database)`, `AOF(Append Only File)`, `RDB와 AOF의 결합` 등이 있다.
각각의 장단점과 사용 시 고려해야 할 사항들에 대해 이해하고 적절하게 구성하여야 한다.


# RDB
RDB는 압축된 데이터 세트의 스냅샷을 저장한다.
Redis의 스냅샷 기능은 데이터 세트의 상태를 디스크에 주기적으로 저장하는데, 이 파일을 Redis 데이터를 백업하거나, 시스템 재시작 시 데이터를 복구하는 데 사용된다. 기본적으로 Redis는 dump.rdb라는 binary 파일에 데이터 세트가 저장된다.

사용자가 스냅샷에 대한 트리거를 설정 할 수 있다.
```shell
save 60 1000
# 1000개의 key가 변경된 경우 60초마나 덤프
```
또는 사용자가 수동으로 `SAVE` 또는 `BGSAVE` 명령을 호출하여 스냅샷을 생성할 수도 있다.

Redis가 데이터 세트를 디스크에 덤프할 때, 먼저 Redis는 자식 프로세스를 생성한다. (fork). 이 프로세스에서 임시적으로 RDB 파일을 생성한 뒤, 성공적으로 덤프가 완료되면 기존 파일을 덮어씌우는 식으로 작동한다.

## 장점
- 백업에 아주 유용하다.
일정한 간격으로 스냅샷을 생성하면, 해당 시점의 데이터 세트로 복원하면 되기 때문.

- 단일 파일로서 다른 위치로 전송하기 용이하다. (로컬 백업, Aws S3)

- Redis 성능 최적화에 도움이 된다. 디스크 I/O 작업을 redis 프로세스가 수행할 필요가 없기 때문.

- 대규모 데이터 세트에서 AOF에 비해 재시작이 빠르다

- Replica 환경에서 부분동기화가 가능하다.

## 단점

- RDB스냅샷 주기 사이에 장애가 발생하면 데이터가 유실 될 수 있다.

- 데이터 세트가 큰 경우, fork()시 시간이 많이 소요되며 클라이언트 서비스에 영향을 줄 수 있다.

# AOF
위 RDB 방식에서는 dump주기 사기에 Redis에 문제가 발생하면 데이터가 유실될 수 있다.
내구성을 높이며 저장하는 방식인 `AOF`를 고려해볼 수 있다.

AOF를 아래 구성 파일에서 설정하여 활성화 할 수 있다.
```shell
#redis.conf
appendonly yes
```
활성화가 된 이후, Client로 부터 쓰기 명령을 수신할 때 마다 AOF에 해당 명령이 추가된다. Redis가 재시작 하는 경우, AOF에 쓰여진 명령들이 실행되며 복원된다.

Redis 7부터는 멀티 파트 AOF 메커니즘을 사용하는데, 단일의 `base AOF` 파일과 여러개의 `incremental AOF` 파일로 분리되어 작동한다. base에서는 데이터 초기 스냅샷을 저장하고, `incremental`파일에서는 base 이후 쓰기 작업에 대한 명령들을 저장하게 된다.

## Log rewriting
Redis에 데이터가 증가하면 비효율적인 AOF가 작성될 수 있다. 예를들어 동일한 key에 대해 `INCR`을 100,000번 수행한 경우, 쓰기 작업이 모두 추가되지만 실제 필요한 데이터는 하나이다.
효율적인 AOF 저장 공간 사용을 위해 쌓인 로그들에 대해 재작성(rewriting) 작업이 필요하게 된다.


rewrite는 기존 `AOF`파일에 계속 로그가 추가되는 동안, 현재 데이터 세트를 만드는 데 필요한 최소한의 작업 집합으로 완전히 새로운 파일을 생성하고 해당 파일이 준비되면 기존 AOF가 아닌 새 AOF파일로 전환하여 로그가 쌓이게 된다.

`BGREWRITEAOF` 명령을 통해 클라이언트 서비스를 중단하지 않고 백그라운드에서 AOF rewirte 작업을 수행 할 수 있다. 메모리에 존재하는 데이터 세트를 재구성하는 데 필요한 최단 명령 시퀀스를 작성한다고 한다.

## fsync

AOF는 어떤 주기로 얼마나 로그를 `fsync(disk에 flush)`하는지에 따라 내구성(durable)에 영향을 미친다.
어느 시점에 `fsync`에 대한 구성을 지정할 수 있는데, 아래와 같은 3가지 옵션이 존재한다.

- `appendfsync always`
새로운 명령이 AOF에 추가될 때마다 `fsync`한다. 느리지만 안전하다.
- `appendfsync everysec`
매초마다 `fsync`. 충분히 빠르지만, 재해가 발생하면 1초의 데이터가 손실될 수 있다.
- `appendfsync no`
`fsync` 설정을 따로 하지 않고 운영 체제에 따라간다. `Linux`에서는 30초마다 데이터를 `flush`한다고 한다.


## 장점
- 내구성(durable)에 유리하다. 모든 쿼리마다 `fsync`를 통해 지정한 정책에 따라 높은 성능의 쓰기 작업이 진행되기 때문에 장애 발생시 손실의 정도가 매우 적다.

- AOF 파일은 자동으로 안전하게 재작성될 수 있다.

- AOF내 모든 로그가 이해하기 쉽고 파싱할 수 있는 형식으로 기록된다.

## 단점

- AOF 파일은 동일한 데이터에 대해 RDB 파일보다 일반적으로 크다.

- `fsync` 정책에 따라 RDB보다 느릴 수 있다.

- Redis 7.0 이전 버전에서는 AOF 재작성에 많은 메모리를 사용할 수 있다.

- 재작성 중에 도착하는 모든 쓰기 명령은 두 번 디스크에 기록되게 된다.


59 changes: 59 additions & 0 deletions redis/week06/taeyeon/Scale with Redis Cluster.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
> https://redis.io/docs/management/scaling/


# Scale with Redis Cluster
`Redis 클러스터`라는 배포 topology로 수평적 확장이 가능하다.


# Redis Cluster 101
`Redis Clutser`는 데이터가 여러 Redis 노드에 자동으로 샤딩되며 Redis를 운영/실행하는 방법을 제공한다. `Redis Cluster` 노드의 일부에 문제가 발생해도 운영가능하며 어느 정도의 가용성을 기대할 수 있다. `Master` 다운되면 `Redis Cluster`를 사용할 수 없다.

이러한 목적으로 다음과 같은 기능을 사용할 수 있다.
1. 데이터를 여러 노드에 자동으로 분할
2. 노드의 하위 집합이 다운되도 Client와의 작업을 계속 수행 할 수 있다.(가용성)

### Redis Cluster TCP ports
모든 `Redis Cluster`는 클라이언트와 통신하는(e.g. 6379) 포트와 _`bus port`_라고 하는 포트가 필요하다. 일반적으로 `bus port`는 데이터 포트에 10000을 추가하여 설정되지만(e.g. 16379) 변경할 수 있다.

`bus port`를 통해 `Cluster`는 장애 감지, 구성 업데이트, 장애 조치 권한 부여 등을 통신한다.그렇기 때문에 Client에서 해당 `bus port`를 사용하지 않도록 하는 것이 좋다.

Redis Cluster가 정상적으로 동작하기 위해선 `data port`(for client)와 `bus port`가 모두 개방되어 있어야 한다.

### Redis Cluster data sharding
`Redis Cluster`는 일관된 해싱 방식을 사용하지 않고, 데이터의 키가 개념적으로 해시 슬롯이 되는 형태로 샤딩을 제공한다. 16384개의 해시 슬롯이 있는데, 키에 대한 [CRC16](http://wiki.hash.kr/index.php/CRC-16)를 연산한 뒤 16384로 모듈로(modulo, `%`)연산을 수행하여 할당한다.

`Redis Cluster`의 각 노드는 해시 슬롯의 하위 집합을 담당하게 되고, 3개 노드로 구성된 `Cluster`에서 `노드 A`는 `0 ~ 5500`, `노드 B`는 `5501 ~ 11000`, `노드 C`는 `11001 ~ 16383` 까지의 해시 슬롯을 담당하게 된다.
이렇게 구성하여 노드의 변동에 대해 해시 슬롯 재분재를 통해 작업이 간단하며 중단될 필요가 없어진다.

또, `Redis cluster`는 node가 자체적으로 `master-replica` 모델을 사용한다. 만약 위 예시에서 `노드 B` 에 장애가 발생하면 `5501 ~ 11000`의 해시 슬롯 사용이 불가하여 `Cluster`에 문제가 발생할 수 있기 때문에 replica 노드를 운용하여 가용성 높은 Cluster 환경을 제공한다.

### Redis Cluster consistency guarantees
Redis Cluster 는 강력한 일관성(strong consistency)를 보장하지 않는다고 한다. 특정 조건에서 승인된 쓰기 작업이 `Redis Cluster`에서 손실 될 수 있다는 것이다.

아래와 같은 이유들로 `"강력한 일관성"`이 보장되지 않는다.
- 비동기 복제 사용
Redis Cluster는 비동기 복제를 사용하기 때문에 복제 대상에게 잘 전달되었는지에 대한 응답 없이 client에게 쓰기 응답을 전달한다. 이 상황에서 Master만 쓰기 작업을 수행한 후, 복제본에 쓰기 전파를 하기 전에 다운되고 이를 감지한 다른 노드가 master로 승격되면서 영구적으로 손실될 수 있다.

flush(일종의 동기화 작업)하기 전에 클라이언트에 응답하는 것은 성능이 매우 낮아지므로 `Redis Cluster`는 비동기 방식으로 복사한다.

`Redis Cluster`도 `WAIT` 명령을 지원하지만, 완전하게 일관성을 보장하진 않는다고 한다.

또, node timeout이 발생하면 master는 해당 노드에 문제가 발생했다고 간주하고 Cluster 구성을 변경 하면서 유실 될 수 있다.

### Redis Cluster configuration parameters

`Redis Cluster`를 구성할 때는 각 Redis 노드의 redis.conf 파일에서 여러 설정을 지정할 수 있다.

- cluster-enabled <yes/no>
Redis 인스턴스에서 Redis Cluster 지원을 활성화 한다.

- cluster-node-timeout <milliseconds>:

Redis 노드가 실패한 것으로 간주되기 전까지 허용되는 최대 시간 설정

- cluster-slave-validity-factor <factor>:
복제본이 마스터의 장애 조치를 자격 여부 설정. 0으로 설정하면 복제본은 항상 마스터의 장애 조치를 시도한다.

- cluster-allow-reads-when-down <yes/no>:

클러스터가 실패로 표시될 때 노드가 읽기 쿼리를 제공할 수 있는지 여부 설정. 'yes'로 설정하면, 실패 상태에서도 노드에서 읽기 작업은 허용된다.