Devlog
article thumbnail
Published 2023. 3. 27. 09:22
[Redis] Introduction to Redis 회사/스터디

사내 기술 스터디 중 Redis를 맡게 되었다.

주임님과 한 팀으로 짜여진 기술 스터디 추진 계획으론 상반기에는 이론/기술, 하반기에는 (사내) 프로젝트 구현이다.

블로그에 한 번 더 정리함으로서 좀 더 내용을 이해하고자 한다.

 

참고자료

여러 블로그와 사이트도 찾아봤지만 가장 주축이 되었던 내용은 아래 두 가지

 

https://forward.nhn.com/2021/sessions/16

 

Redis 야무지게 사용하기

Redis, 얼마나 알고 사용하고 계신가요? Redis를 사용하는 사람들이라면 이것만큼은 꼭 알아야 할 내용들을 공유하고자 합니다. 어디 가서 Redis 좀 써봤다 얘기할 수 있도록, 대충 쓰는 것이 아닌 '

forward.nhn.com

https://product.kyobobook.co.kr/detail/S000001057858

 

Redis 운영 관리 | 강대명 - 교보문고

Redis 운영 관리 | 『Redis 운영 관리』는 Redis의 특징과 함께 어떻게 운영하고 관리해야 하는지를 알아보는 책이다. Redis 복제 모델과 복제시 주의해야 할 사항을 학습한다. 저자는 현장에서 얻은

product.kyobobook.co.kr

 

 

1주차: Introduction to Redis

 

1. 레디스 정의

  • Redis (Remote Dictionary Server)는 빠른 속도와 다양한 데이터 타입을 지원하는 오픈소스 기반의 인메모리 데이터 구조 저장소
  • 대규모 분산 시스템에서도 활용될 수 있는 다양한 기능과 높은 성능, 안정성 등의 장점을 가지고 있음
  • 캐싱, 세션 관리, 메시지 큐, 랭킹 등 다양한 분야에서 사용 중

  1.1 Key-Value 스토어

    • Key-value 형태의 데이터 저장소로 간단한 명령어를 통해 데이터를 저장할 수 있음
    • Value에는 String, Bitmaps, … 등의 컬렉션 타입이 올 수 있음
    • Key 문자열이며 최대 512MB까지 사용 가능

1.2 컬렉션 지원

 

  • Redis는 분산 서버 환경에서 컬렉션을 사용할 수 있어 전체적인 서비스를 설계하거나 구현할 때 많은 이점을 얻을 수 있음
  • 개발의 편의성을 올려주고 난이도를 낮춰주는 요소로 상황에 적합한 컬렉션을 선택하고 이용하는 것이 중요

 

1.3 Pub/Sub 지원

  • Publish/Subscribe 기능 지원으로 서버 간 통지가 필요할 때 해당 기능이 매우 유용: 메시지 브로커로서 활용
    • 메시지 브로커: 데이터들을 안전하고 효율적으로 전달하기 위해 서비스로부터 메시지를 받아 비동기적으로 클라이언트에게 전달해주는 미들웨어

보통의 일반적인 경우: API를 통해 서버 간의 동기적 통신서버로부터 메시지를 전달 받아 큐에 보관한 후알맞은 클라이언트에게 전달해주는 메시지 큐 구조의 브로커 사용

 

Redis 경우: 메시지 브로커의 기능을 가지지만 메시지를 저장하지 않고 클라이언트에게  메시지를 전달한 후  이를 바로 삭제 (Pub/Sub 구조)

 

클라이언트가 하나의 토픽을 구독(subscribe), 해당 토픽으로부터 발행(publish)되는 메시지들을 받는 구조

 

 

토픽이라는 매개체를 통해서 메시지를 전달하므로 수/발신자가 서로를 알지 못하더라도 메시지 송/수신 가능

 

Redis에서의 pub/sub는 전송한 메시지의 내용을 저장하지 않고 클라이언트에게 전달한 후 삭제하기 때문에 

push 메시지처럼 실시간으로 로그인 된 사용자에게 메시지를 전달해야 하는 기능을 구성할 경우 유용 

 

 

1.4 디스크 저장

  • Redis는 In-Memory 데이터 스토어로 모든 데이터가 메모리에 저장됨
  • 레디스 인스턴스 또는 서버 재시작시 모든 데이터가 유실되어 복제 기능을 사용해도 사람의 실수 발생시 데이터 복원  불가 
  • 레디스를 캐시 이외의 용도로 사용한다면 적절한 데이터 백업이 필요함

디스크 저장 종류

  • AOF(Append Only File)
    • 데이터를 변경하는 커맨드가 들어오면 커맨드를 그대로 저장 기록이 남아있음
    • 데이터가 추가되기만 해서 대부분 RDB 파일보다 커지게 됨
    • AOF 파일은 주기적으로 압축, 재작성 과정을 거쳐야 함 
  • RDB(snapshot)
    • 저장 당시의 메모리에 있는 데이터가 그대로 스냅샷 찍듯 파일로 저장

⇒ AOF, RDB 둘 다 커맨드를 이용해 직접 파일 생성이 가능함, 원하는 시점에 파일이 자동 생성될 수도 있음

 

 

자동/수동 파일 저장 방법(AOF write, RDB save)

 

자동  redis.conf 파일에서 auto-aof-rewrite-percentage 옵션
(파일 크기 기준, 압축되는 시점 지정)
redis.conf 파일에서
SAVE 옵션
(시간 기준, 시간 단위 저장 가능)
수동 BGREWRITEAOF 커맨드 이용
cli 창에서 수동으로 AOF 파일 재작성
BGSAVE 커맨드를 이용
cli 창에서 수동으로 RDB 파일 저장

 

RDB VS AOF 선택 기준

  • 만약 redis를 캐시로만 사용한다면 굳이 RDB, AOF를 사용 할 필요 없음
  • 백업은 필요하지만 어느정도 데이터 손실이 발생해도 괜찮은 경우: RDB 단독 사용
    • 활용 예시  
      • redis.conf 파일에서 SAVE 옵션을 적절히 사용  
      • SAVE 900 1 900초 동안 1개 이상의 키가 변경되었을 때 RDB 파일을 재작성
  •  장애 상황 직전까지의 모든 데이터가 보장되어야 할 경우: AOF 사용 (appendonly yes)
    • 활용 예시  
      • APPENDFSYNC 옵션이 everysec인 경우, 최대 1초 사이의 데이터 유실 가능 (기본 설정)
  • 제일 강력한 내구성이 필요한 경우: RDB, AOF 둘 다 사용

 

1.5 복제

  • Replication: 복제 
    • 단순한 복제 연결
    • replicaof 커맨드를 통해 간단하게 복제 연결
    • 비동기식 복제 ⇒ 마스터에서 복제본에 데이터가 잘 전달 됐는지 매번 확인하고 기다리진 않음
    • HA 기능(High Availability)이 없으므로 장애 상황시 수동 복구
    • replicaof no one 리플리카 노드에 직접 접속, 복제를 끊어야 함
    • 애플리케이션에서 연결 정보 변경하여 배포 작업
  • Sentinel: 센티널 노드 필요, 센티널 노드는 일반 노드들을 모니터링 하는 용도 
    • 자동 페일오버 가능한 HA (High Availability)
    • 마스터가 비정상일 때(다운) 자동으로 페일오버: 기존의 리플리카 노드가 마스터 노드가 됨
    • sentinel 노드는 항상 3대 이상의 홀수로 존재해야 함
    • 이때 sentinel 구조 사용시 센티널 프로세스를 추가로 띄워야 함
    • 이때 어플리케이션에서는 센티널 노드만 알고 있으면 됨, 센티널이 변경된 마스터 정보로 바로 연결 시켜줌
  • Cluster: 최소 3대의 마스터 필요, 샤딩 기능 제공
    • 스케일아웃과 HA 구성
    • 키를 여러 노드에 자동으로 분할해서 저장 (샤딩 기능: 데이터가 여러 마스터 노드에 자동으로 분할되어 저장 기능 제공)
    • 모든 노드가 서로를 감시하여 마스터 비정상 상태일 때 자동으로 페일오버 진행
    • 최소 3대의 마스터 노드가 필요, 리플리카 노드를 하나씩 추가하는게 일반적인 구조

아키텍처 선택 기준

 

HA(High Availability) 기능: 자동으로 페일오버 되어야  할까?

샤딩 기능: 서비스 확장을 위해 scale out이 필요할까?

Stand-Alone: 마스터 하나만 띄운 구조

 

 

 

2. 다른 데이터베이스와의 비교

 

속도 초당 100,000QPS 이상 초당 100,000QPS 이상
자료구조 Key-Value, List
Hash, Set
Sorted Set 등 지원
Key-Value만 지원
데이터 저장 Memory, Disk Memory
안정성 특성을 잘못 이해할 경우,
프로세스 장애 발생
(ex. 싱글스레드)
장애 거의 없음
응답 속도의 균일성 Memcached에 비해서
균일성이 떨어질 수 있음
전체적으로 균일함

Redis와 Memcached의 메모리 할당 구조의 차이로 인해 발생

  • Memcached : 내부적으로 메모리 할당을 다시 하지 않고 관리하는 형태 (slab 할당자 이용)
  • Redis : jemalloc을 사용하여 매번 malloc과 free를 통해 메모리 할당이 이루어짐
    • 메모리 단편화 발생  -> 할당 비용으로 인해 응답속도가 느려짐
    • 대규모 서비스에서도 Redis를 많이 도입, 일반적인 경우에는 크게 문제되지 않는 사항

 

3. 기업 활용 사례

  • 주로 캐싱, 세션관리에 사용
  • 공연 티켓 정보, SNS 타임라인, 채팅 등 여러 분야에서 사용

3.1 티켓링크

  • 공연 정보 캐싱
  • look-aside 방식
    • 레디스에 찾는 키가 없다면 애플리케이션은 DB에 접근해서 데이터를 직접 가지고 온 뒤 레디스에 저장
    • 티켓 오픈 전 상품의 정보를 미리 DB에서 cache로 밀어 넣어줌(cahe warming)

 

3.2 트위터

  • 사용자의 타임라인 캐싱
  • Redis의 List 이용
    • RPUSHX 커맨드 이용, 캐싱되어 있는 타임라인에만 추가
    • 일정 기간, 로그인되지 않은 사용자의 타임라인은 삭제 처리

1. 내가 트윗을 함 2. 내 팔로워들의 타임라인 캐시에 내 트윗 ID를 추가함 3. 내 팔로워들이 자신들의 타임라인에 들어가면 타임라인 캐시에 있는 나의 Tweet ID로 DB에 요청함

 

3.3 세션 관리

  • 세션 객체는 Key에 해당하는 SESSION ID와 이에 대응하는 Value로 구성
  • 세션 조회 및 검증시 빠른 시간 내에 처리 필요

spring:session:sessions:expires:(session id) string 해당 세션의 만료 키
spring:session:expirations:(expire time) set expire time에 삭제될 세션 정보
spring:session:sessions:(session id) hash 세션의 생성 시간, 
마지막 세션 조회 시간, 
최대 타임아웃 허용 시간,
 해당 세션에 저장한 데이터

세션 클러스터링

  • 다중 서버 환경에서 사용자가 서비스 이용 중 서버에 문제가 생겨 다른 서버로 재접속하는 경우에도 세션을 유지하기 위해 세션 클러스팅이라는 방식을 사용할 수 있음
  • 세션 클러스팅 방식은 사용자의 접속이 server1으로 접속 되고 로그인을 통해 세션이 생성되면  이 세션을 다른 모든 서버로 세션을 보내주기 때문에, 접속한 서버가 server1에서 server2나 server3로 바뀌게 되더라도 세션을 계속 유지한 채로 사용할 수 있음
  • 모든 사용자의 세션을 각각의 서버에 모두 보내주게 되면 서버 메모리에 상당한 부담이 가는 치명적 단점

세션 스토리지 분리 방식

  • 세션을 관리하는 서버를 별도로 두어 사용하는 세션 스토리지 분리 방식 사용으로 해당 단점 보완
  • 서버에서 세션을 Redis 서버로 보내주어 세션을 관리하면 사용자의 서버 접속 경로가 바뀌게 되더라도 세션이 서버에서 관리되지 않고 별도 외부 서버에서 관리되고 있기 때문에 세션이 계속 유지된채로 사용할 수 있음
  • 세션을 저장하고 있는 Session storage 자체에 장애가 발생할 경우 모든 세션을 잃어버려 세션을 사용하는 모든 서버에 영향이 갈 수 있다는 단점
    • 세션 저장소를 하나 더 구성하는 방법(즉, 마스터-슬레이브 복제)으로 해당 문제를 해결

 

3.4 Line Live

LIVE 채팅 시스템 사용자 설정 동기화
Redis Pub/Sub

LIVE에서 사용되는 채팅 시스템의 경우 사용자가 자신의 코멘트를 돋보이도록 배경과 글자 등을 설정 하는 기능이 있으며 설정된 정보가 함께 LIVE를 시청하고 있는 모든 사용자에게 실시간으로 동시에 반영되어야 함

이를 위해 LINE에서는 레디스의 Pub/Sub 을 사용

 

  • 사용자가 채팅관련 설정을 하게되면, 이 설정정보는 MySQL에 저장됨과 동시에 모든 사용자에게 동기화 되기 위해 Redis에도 Publish
  • 리슨 상태인 챗의 웹 소켓 서버는 published된 해당 정보를 subscribe해서 로컬 메모리에 캐싱
  • 이때 subscribe process는 전체 웹 소켓 서버에서 동시에 진행되기 때문에 결과적으로 동일한 타이밍에 전체 서버에 설정이 반영

 

이렇게 반영된 설정은 해당 사용자가 코멘트를 입력시, 설정된 데코레이션과 함께 모든 사용자에게 전송

 

 

4. Redis 데이터 유형 및 커맨드

  • String
    • 기본적인 데이터 타입
    • SET, GET
    • SET 커맨드를 이용해 저장되는 데이터는 모두 String 형태로 저장
  • Bitmap
    • 비트맵은 String의 변형
    • BIT 단위의 연산 가능
  • Lists
    • 데이터를 순서대로 저장하여 Stack, Queue로 사용하기 적절
    • LPUSHX, LPOP, RPUSHX, RPOP
  • Hashes
    • 하나의 키 안에 여러 개의 filed와 value 쌍으로 데이터 저장
    • HSET, HGET
  • Sets
    • 중복되지 않은 문자열의 집합
    • SADD, SREM, SISMEMBER
  • Sorted Sets
    • 중복되지 않은 문자열의 집합
    • 모든 값은 score 값으로 정렬
      • 데이터가 저장될떄부터 score 순으로 정렬, 만약 score가 같을 때는 사전 순으로 정렬되어 저장
    • ZADD, ZRANGE, ZRANK
  • HyperLogLogs
    •  
    • 대용량 데이터를 카운팅 할 때 사용 (중복되지 않은 값) 
      • HyperLogLogs는 unique item이 ADD 될 때마다 counter의 값을 증가 시키며 만약 unique하지 않은 item이 ADD된 경우 아무 일이 일어나지 않음
    • 저장된 데이터 확인 불가능
    • 저장된 값이 몇 건이던 간에 모두 12KB로 고정
    • PFADD, FPCOUNT
  • Stream
    • Log를 저장하기 가장 좋은 자료구조 
      • append-only 방식으로 저장, 중간에 데이터가 바뀌지 않음
    • 일반적으로 ID 값을 지정하지 않고, ‘*’(애스터리스크)로 입력하는데, 이 경우 레디스가 ID를 해당 데이터가 저장된 시간으로 지정하여 저장 후 ID를 반환
    • 이 값 뒤로는 Hashes처럼 key-value 쌍으로 데이터 저장

 

 

 

이론만 봤을 땐 확실히 복제 부분이 어렵긴하다

profile

Devlog

@덩이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그