심층분석

[2] Redis

j9972 2024. 3. 12. 01:08
728x90

Redis 소개

Redis는 key-value 구조의 비정형 데이터를 저장하고 관리하기 위한 DBMS입니다.

 

데이터베이스, 캐시, 메시지 브로커로 사용되며 In-Memory 데이터 구조를 가진 저장소이며, 오픈소스로써 NoSQL로 분류되기도 합니다. ( PUB/SUB 형태의 기능을 제공하여 메세지 전달이 가능합니다. )

 

또 Redis는 Remote Dictionary Server의 약자로써 외부에서 사용 가능한 key-value 쌍의 해시맵 형태의 서버라 별도의 쿼리문 없이 key 값으로 빠르게 데이터를 가져올 수 있습니다.

 

하지만, 메모리에 데이터를 저장하기에 저장 공간에 제약이 있어서 주로 보조 데이터 저장소로 사용되며, 이를 극복하기 위해서 레디스 클러스터 기능을 제공하여 주 저장소로도 사용합니다.


Cache, Memory Hierarchy

Redis는 In-Memory Database 로써 캐시 영역에 존재하는 데이터베이스 입니다.

 

기본적으로 데이터베이스는 ssd에 저장함으로써 컴퓨터 전원이 꺼져도 저장을 하지만 데이터에 접근하는데 시간이 조금 걸린다는 특징이 있습니다.

반면, Redis는 데이터베이스 보다는 더 자주 접근하고 덜 자주 바뀌는 데이터를 Memory 상에 저장해서 빠르고 쉽게 접근하자는 개념에서 등장하였습니다.

 


 

 

동작 원리

 

기존의 Disk에 저장되어 데이터의 읽고/쓰기의 시간을 향상하기 방법으로 사용하는 In-Memory 방식은 다른 방식으로도 구현할 수 있다고 생각할 수 있습니다

 

가령 key-value 특징을 갖는 HashMap을 사용해도 되지 않을까 생각할 수 있습니다. 

하지만 일관성 문제와 경쟁상태 문제가 가능합니다

 

서버가 여러대인 경우 각 HashMap은 각기 다른 데이터를 보유하기에 일관성 문제가 가능하며,

멀티 쓰래드 환경에서 여러 쓰래드가 경합하며, Context Switching이 주기적으로 발생하다 보면 경쟁상태가 발생하며 원치 않은 결과가 발생이 가능합니다.

 

그렇기에 Redis는 경쟁상태를 방지하기 위해서 싱글 쓰레드 환경에 기반하여 동작합니다.

Redis 자료구조는 임계 영역에 동기화 환경을 제공합니다.

( 여러 프로세스가 임계영역에 접근하지 못하도록 동기화를 시켜 경쟁 상태를 방지하여 원하는 결과를 반환하도록 해줍니다 )

 

결국, 캐시의 기능으로 빠른 연산 및 접근이 필요하거나 여러 서버에서 같은 데이터를 공유해야하는 상황에서 적극 사용하면 됩니다

 


주의 사항

Redis는 싱글 스레드이기에 시간복잡도와 메모리 단편화로 인한 메모리 관련으로 주의할 점들이 있습니다.

 

1) 시간 복잡도 - O(n) 이 걸리는 경우

 

특정 데이터를 찾을 때 모든 원소를 다 뒤져봐야 하므로, 모든 key를 가져오는 연산이나, getAll 처럼 모든 데이터를 다루는 경우에 데이터 양이 백만건, 천만건 이렇게 많아지면 시간복잡도가 상당하기에 주의해야한다.

 

이렇게 너무 많은 시간이 걸리면 나머지 요청들이 모두 거절되고 서버가 다운 될수도 있으니 주의하자

 

2) 메모리 단편화

 

Redis를 사용할때는 적절한 메모리는 주는것이 좋다.

지속적으로 set 커맨드가 유입되면 이로 인해 key 삭제되면서 memory (외부/내부)단편화가 심해질 수 있는데, 이로 인해서 OOM이 발생이 가능할 수 있으니 주의해야 합니다.

( Fragmentation ratio 수치를 통해서 메모리 사용량 확인할 수 있다 )

 

3) 데이터의 유실 문제

 

Redis는 휘발성을 가진 메모리상의 데이터 저장소이므로 항상 데이터 유실에 대한 문제를 염려해야합니다,

이에 대해서는 아래 데이터 백업 방식을 통해서 설명하겠습니다.


데이터 백업 방식 [ persistence ]

Redis는 In-memory 데이터 스토어

  • 서버 재시작 → 모든 데이터 유실
  • 복제 기능을 사용해도 사람의 실수 발생시 데이터 복원 불가
  • Redis를 캐시 이외의 용도로 사용한다면 적절한 데이터 백업 필요

저장 방법 2가지

 

영구 저장하는 방법 2가지

  1. AOF - Append Only File
    • 데이터 변경 커맨드까지 모두 저장한다.
    • 자동 저장시 : redis.conf 파일에서 auto-aof-rewrite-percentage 옵션으로 크기 기준으로 저장 가능
    • 수동 저장시: BGREWRITEAOF 커맨드를 이용해 CLI창에서 수동으로 AOF 파일 재작성이 가능하다
  2. RDB - snapshot
    • 저장 당시 메모리에 있던 데이터들만 그대로 저장
    • 자동 저장시 : redis.conf 파일에서 SAVE 옵션으로 시간 기준으로 저장할 수 있다
    • 수동 저장시 : BGSAVE 커맨드를 이용해 cli 창에서 수동으로 RDB파일을 저장할 수 있다.

RDB VS AOF ( 언제 무엇을? )

  • 백업이 필요하지만, 어느 정도 데이터 손실 발생해도 괜찮은 경우
    • RDB 단독 사용
    • redis.conf 파일에서 SAVE 옵션을 적절히 사용한
  • 장애 상황 직전까지 모든 데이터가 보장되어야 하는 경우
    • AOF 사용
    • APPENDFSYNC 옵션이 everysec인 경우 최대 1초 사이의 데이터 유실 가능 ( 기본 설정 )
  • 제일 강력한 내구성이 필요한 경우
    • RDB & AOF 동시 사용

아키텍쳐

  • replication : 단순한 복제 연결
    • replicaof 커맨드를 이용해 간단하게 복제 연결
    • 비동기식 복제 [ 복제가 잘되었는지 확인하지 않음 ]
    • HA 기능이 없으므로 장애 상황시 수동 복구
      • 장애 발생시 스프링에서 새로운 Redis 서버의 연결 정보를 변경해야함
  • sentinel : 자동 페일오버 가능한 HA 구성
    • sentinel 노드가 다른 노드( master, replica ) 감시
    • 마스터가 비정상 상태일 때 자동으로 페일오버 ( 자동 복구 )
    • 장애 발생시 연결 정보 변경 필요 없음
    • sentinel 노드는 항상 3대 이상의 홀수로 존재해야함
      • 과반수 이상의 sentinel이 동의해야 페일 오버 진행
  • cluster : 스케일 아웃과 HA 구성
    • 키를 여러 노드에 자동으로 분할해서 저장(샤딩)
    • 모든 노드가 서로를 감시하며 마스터 비정상 상태일 때 자동 페일오버
    • 최소 3대의 마스터 노드 필요

 

아키텍쳐 선택 기준

아키택쳐 선택하는데 있어서 사진을 참고하여 레디스의 사용 목적이 무엇이며, Redis가 싱글 스레드임을 알고 아키텍쳐를 선택하면 될 거 같다.

 


장애 사례, 추가 이슈

Redis는 메모리에 데이터를 저장하기 때문에 물리메모리(RAM) 용량보다 더 많은 데이터를 사용하게 될 경우 메모리 부족으로 인해 swap이 발생하여 Redis의 성능저하가 가능하므로, 메모리 측면에서 제대로 관리하지 않으면 장애가 발생 가능하다.

 

[ 이슈 1 ]

Swap 메모리 설정 시, 실제 메모리가 부족하더라도 시스템다운 및 프로세스 멈춘현상(Hang)을 방지할 수 있어 보다 안정적일 수 있지만, 디스크의 공간을 메모리처럼 사용하게 되어 처리 속도가 떨어져 성능 저하로 이어질 수 있다.

 

[ 이슈 2 ]

Swap이 없는 상태에서 물리 메모리 양보다 더 많은 데이터를 사용한 경우 OOM 일으킬 수 있다.

 

참고

https://velog.io/@msung99/Redis-CS-%EA%B4%80%EB%A0%A8-%EC%A7%80%EC%8B%9D%EB%B6%80%ED%84%B0-%EB%9C%AF%EC%96%B4%EB%B3%B4%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-Redis-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0%EC%99%80-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98%EC%9D%84-%EC%82%B4%ED%8E%B4%EB%B3%B4%EC%9E%90

 

Redis 에 개념에 대해 정리해봤다.

Redis 를 단순히 명령어만 치지말고, 어떤 원리로 동작하는것인지 자세하게 파해쳐봅시다! 🧐

velog.io