Skip to content

Commit 19d862a

Browse files
committed
7장 레플리카 추가
1 parent 4ac0772 commit 19d862a

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

docs/Redis/실전레디스/실전.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,174 @@ AOF는 fsync로 디스크에 쓰기 작업을 하므로 appendfsync 지시자
120120
121121
### 5.2.2 쓰기 관점 아키텍처
122122

123+
#### Write-Through 패턴
124+
125+
> DB 먼저, 이후 Redis 저장
126+
127+
1. 애플리케이션은 DB에 데이터 저장
128+
2. 애플리케이션은 1번과 같은 데이터를 Redis 서버에도 저장
129+
130+
- **장점**
131+
- 레디스 서버 내의 캐시 데이터가 항상 최신 상태를 유지
132+
- 읽기 작섭 오버헤드가 줄어듬
133+
- **단점**
134+
- 사용하지 않는 캐시 데이터 생성 가능
135+
- 쓰기 작업 시 DB와 캐시에 모두 쓰기를 해야 하므로 오버헤드가 큼
136+
137+
138+
#### Write-Back 패턴
139+
140+
> 캐시 저장 후, 일정 시간 지연됨녀 DB를 비동기 업데이트
141+
142+
- **장점**
143+
- Redis 서버 내의 캐시 데이터가 항상 최신 상태 유지
144+
- 쓰기 작업을 빠르게 처리
145+
- **단점**
146+
- 데이터 손실 위험
147+
148+
#### Write-Around 패턴
149+
150+
> DB 저장, Redis 업데이트
151+
152+
- **장점**
153+
- 데이터 손실 위험 낮음
154+
- **단점**
155+
- 구현 방법과 읽기 관점 아키텍처에 따라 달라질 수 잇음
156+
157+
### 5.2.3 아키텍처 안티 패턴
158+
Redis 캐시 노드가 다운되면 애플리케이션 사용이 어려울 수 있다. 이를 위해 아키텍처를 재검토할 필요가 있다.
159+
160+
지연 로딩 아키텍처에서 캐시 노드가 다운된 경우 미치는 영향도 사전에 고려해야 한다.
161+
162+
### 5.2.4 데이터 저장소로서의 레디스 아키텍처
163+
**[주의 사항]**
164+
- [ ] 사용하는 Redis 기능이 데이터 저장소로서 요구사항을 충족하는지 확인
165+
- [ ] 문제 발생 시 복구 방법을 확인
166+
- [ ] 다른 RDB와 결합하여 사용할 경우, 롤백 발생 시 데이터 일관성에서 애플리케이션 구현에 문제가 없는지의 여부 고려
167+
- [ ] 레디스의 레플리케이션 기능이나 스냅숏 생성을 사전에 준비
168+
169+
Redis를 단독 저장소로 사용할 경우, 영속성이라는 트레이드오프를 고려해야 한다.
170+
171+
## 5.3 모범 사례
172+
### 5.3.1 TTL 설정
173+
캐시는 데이터가 소실되어도 큰 문제 없는 데이터를 저장한다. 따라서 장기간 데이터를 저장할 필요가 없기에 TTL을 설정하도록 하자.
174+
175+
이를 통해 지연 로딩 패턴을 통해, RDBMS의 부담을 줄일 수 있다.
176+
또한, 데이터의 최신 상태를 유지하도록 강제하며, 메모리 압박도 방지할 수 있다.
177+
178+
#### TTL 확인
179+
`INFO Keyspace` 명령어로 확인 가능
180+
181+
### 5.3.2 제거 정책 설정
182+
maxmemory 지시자로 설정 값 도달하면, Redis는 메모리 확보를 위해 키를 제거 한다.
183+
maxmemory-policy 지시자를 캐시 서버로 사용되는 경우, 다음 정책 중에서 선택 가능.
184+
185+
- TTL이 설정된 키를 대싱으로 하는 volatile-로 시작하는 정책을 선택
186+
- 데이터 저장소로 사용하는 경우, 모든 키를 대상으로 allkeys-로 시작하는 정책을 선택
187+
188+
### 5.3.3 백업
189+
- 스냅숏은 요청 처리 스레드로부터 일반 fork 처리를 통해 생성된 스레드로 RDB 파일이 생성되는 방식
190+
- 이때, 백업 등 데이터 셋 이외의 메모리 할당에는 CoW라는 방식 사용
191+
- fork 처리로 생성된 스레드는 fork 처리 직후 부모 스레드와 같은 범위의 메모리 영역을 사용.
192+
- 그 후 마스터와 레플리카에서 변경이 발생하면 각각 개별적으로 메모리 영역을 준비해서 기존에 공유하던 메모리 영역에서 분리하여 사용.
193+
- 읽기 작업만 하는 워크로드면 스냅숏 생성 중에도 메모리 상용량이 크게 증가하지 않음
194+
- 쓰기 작업이 많은 워크로드에선 최대 두 배 가까이 메모리 소비가 증가.
195+
- 따라서, 데이터 영역에 사용하는 메모리양은 Redis가 사용할 수 있는 메모리양의 50% 정도를 여유로 두는게 바람직
196+
197+
- 관리형 서비스 이용하는 경우
198+
- 데이터 이외 용도로 사용하는 메모리 영역예약 가능
199+
- ElastiCache는 reserved-memory-percent 지시자를 제공
200+
- ElastiCache는 일반적으로 메모리 부족 시 포크 처리 없이 스냅숏 생성
201+
- 이 기능 사용하면 포크 작업 중 쓰기 작업이 많아질 대 발생하는 문제 예방 가능
202+
- Redis는 싱글 스레드로 요청을 처리하기에 같은 스레드에서 스냅숏을 생성하면 그 사이 처리해야 하는 요청에 영향을 주게되어 지연 시간이 증가.
203+
- CoW로 메모리 사용이 증가해도 두 배까지 증가하지 않으니 25% 정도의 메모리만 확보해도 충분
204+
205+
### 5.3.4 커넥션 풀링
206+
최대 동시 연결 수는 maxclients 지시자로 설정. 기본값은 10,000
207+
레디스가 열 수 잇는 File Descriptor는 커널에 의해 소프트 제한이지만, 클라이언트의 최대 개수에 32를 더한값이 상한선으로 결정.
208+
209+
210+
## 5.6 보안
211+
ACL(Access Control List)라는 접근 제어 목록 기능을 통해 의도치 않은 접근으로 인한 취약점을 방지한다.
212+
213+
<br/>
214+
215+
# 7. 레플리케이션
216+
쓰기 작업이 있을 때마다 업데이트된 데이터를 다른 서버로 계속 보내 복제하는 것을 의미.
217+
218+
## 7.1 레플리케이션 기능
219+
### 7.1.1 비동기 처리를 통한 구현
220+
레디스의 레플리케이션은 이벤트 루프의 비동기 논블로킹 방식으로 구현됨.
221+
마스터와 레플리카 사이의 데이터 정합성이 보장되지 않음.
222+
223+
### 7.1.2 레플리케이션을 사용할 때 레디스를 연결하는 방법
224+
각 캐시 노드의 IP 주소나 엔드포인트를 기록해두고, 레디스 클라이언트에서 직접 접근하거나 twemproxy 같은 프록시를 통해 여러 레플리카의 요청 라우팅 과정을 자동화.
225+
226+
### 7.1.3 기본적으로 읽기 전용인 레플리카
227+
레플리카에 쓰기 작업이 가능할 경우, 데이터의 일관성이 깨질 위험이 있어, 기본적으로 불가능하도록 설정됨.
228+
`replica-read-only` 지시자를 통해 변경이 가능.
229+
230+
### 7.1.5 레플리케이션 주의사항
231+
마스터에 영속성이 설정되어 있지 않으면, 엔진 재실행하거나 종료하면 데이터 셋이 초기화되어 실행됨.
232+
또한, 레플리카도 초기화되므로 주의해야 한다.
233+
234+
## 7.2 레플리케이션을 시작할 때의 메커니즘
235+
236+
**[레플리케이션 과정]**
237+
1. 레플리카는 PSYNC 명령어로 마스터에 연결 요청. 해당 시점까지 처리한 레플리케이션 ID와 오프셋을 전송
238+
2. 마스터는 요청받은 마스터의 레플리케이션ID와 자신의 에플리케이션 ID가 일치하는지 확인. 오프셋이 레플리케이션 백로그의 버퍼에 있는지 확인.
239+
3. 요청받은 오프셋이 레플리케이션 백로그에 있는지에 따라 처리가 달라짐.
240+
1. 레플리케이션 백로그에서 동기화가 가능한 경우: 요청된 오프셋이 레플리케이션 백로그에 있고, 레플리케이션 백로그에서 동기화가 가능한 경우에는 부분 동기화 실행
241+
2. 레플리케이션 백로그에서 동기화 불가능한 경우: 레플리케이션 중단 중에 마스터가 받은 쓰기 작업 요청의 크기가 버퍼 크기를 초과하여 부분 동기화가 불가능한 경우에는 전체 동기화 실행.
242+
243+
전체 동기화: 요청 처리에 미치는 영향 큼, 모든 상황에서 실행가능
244+
부분 동기화: 요청 처리에 미치는 영향 작음, 조건을 충족할때만 실행 가능
245+
246+
레플리케이션 -> 부분 동기화 -> 불가능하면 전체 동기화
247+
248+
### 7.2.1 전체 동기화
249+
**[전체 동기화 과정]**
250+
1. 요청: Replica가 Master에게 연결 요청(PSYNC ? -1)
251+
2. 스냅샷 생성 (Master): Master는 즉시 BGSAVE를 실행해 현재 메모리에 있는 모든 데이터를 RDB 파일로 저장
252+
3. 파일 전송: 완성된 RDB 파일을 Replica에게 전송
253+
4. 반영 (Replica)
254+
1. Replica 자신의 메모리에 있던 기존 데이터 모두 삭제
255+
2. 전송받은 RDB 파일을 로드
256+
5. 버퍼 내용 처리: RDB를 만드는 동안 Master에 새로 들어온 쓰기 명령들은 Master의 메모리 버퍼에 쌓여있다가, RDB 로드가 끝나면 Replica에게 전소오디어 최종 싱크를 맞춤
257+
258+
### 7.2.2 부분 동기화
259+
**[부분 동기화]**
260+
1. 재연결 요청: Replica가 다시 연결하면서 Master ID와 Offset으로 특정 시점 연결
261+
2. 판단:
262+
1. Master는 백로드 버퍼(원형 큐)를 확인
263+
2. 만약 버퍼에 남아있으면 부분 동기화 성공
264+
3. 만약 버퍼에서 지워졌으면 전체 동기화로 전환
265+
3. 전송: 버퍼에 남아있는 명령어들만 Replica에게 보냄
266+
4. 완료: 매우 빠르게 동기화가 끝남
267+
268+
## 7.4 페일오버
269+
페일오버는 Master 노드가 죽었을 때, 살아있는 Replica 중 하나를 자동으로 새 Master로 승격시켜 서비스를 지속시키는 과정.
270+
Master가 죽었을 때 자동으로 복구하기 위해 사용하는 자동화 시스템을 Redis Sentinel 또는 Redis Cluster라고 한다.
271+
272+
보통 Sentinel 기반 페일오버 과정을 사용한다.
273+
274+
**[페일오버 과정]**
275+
보통 3대 이상의 Sentinel이 서로 협력하여 결정을 내림.
276+
277+
**1. 장애 감지**
278+
Sentinel은 Master에게 계속 PING을 보냄
279+
- SDOWN(Subjective Down - 주관적 다운): 하나의 Sentinel이 Master가 죽었다고 판단하는 단계
280+
- ODOWN(Objective Down - 객관적 다운): 다른 Sentinel이 함께 Master가 죽었는지 판단하는 단계
281+
282+
**2. 리더 선출**
283+
284+
**3. 새로운 Master 선정 및 승격**
285+
- 선정 기준
286+
- 네트워크 연결이 안정적인지?
287+
- 데이터가 가장 최신인지? (Replication Offset이 가장 큰 노드)
288+
- 우선순위 결정(replica-priority)이 높은지?
289+
290+
Sentinel 외의 다른 캐시 노드에게 새 마스터로 REPLICAOF NO ONE 명령어를 보내고, 페일오버 실행한 센티널 노드가 새로운 구성 정보를 브로드캐스트 한다.
291+
292+
**4. 클라이언트 통지**
293+
Spring Boot 같은 애플리케이션은 죽은 Master IP를 알고 있기에, Sentinel은 Pub/Sub을 통해 클라이언트에게 변경된 Master 주소를 알려준다.

0 commit comments

Comments
 (0)