반응형

레디스

  • nosql
    • not only sql
  • 비정형화된 데이터 사용 -> 유연성, 확장성, 실시간 응답
  • 레디스는 key-value형태이고 
    • 그래프, 다큐먼트, 콜롬배이스 형태도 있음
  • in memeory 데이터베이스 -> 모든 데이터가 메모리 위에 있어 디스크까지 가서 받아오지 않아도 돼서 빠름
  • 단순성 - 다양한 자료구조 제공(10가지 이상), 커맨드 처리, 이벤트 루프로 동작(싱글스레드; 한 번에 하나의 작업만 함)
  • 클라의 처리가 빠르고 단순
  • 확장성/고가용성
    • 클러스터 -> 샤딩을 위한 기술
    • 여러개 서버에 나눠서 저장

MSA에서 레디스?

  • 데이터 저장소(권장하지 않음) 쓸 수는 있다(10가지의 자료구조 제공; 개발의 편리성) -> 데이터의 영구저장을 할 수는 있다.(파일)
  • 캐시: 최소한의 리소스로 막대한 처리; 자체 HA 기능 제공
  • 메시지 브로커: pub/sub, event queue, stream

redis 자료구조

  • string(모든 종류의 문자열 저장 가능; 이진 데이터 포함)
    • set/get으로
      • set hello world -> key: hello, value: world
      • get hello -> world
    • 이미지, html 도 가능
    • 최대 512MB
    • string -> string
    • 키도 최대 512MB
    • command
      • incr(1씩 증가) / incrby(지정한 수만큼 증가; 락 안 잡고도 증가시킬 수; mysql은 락을 잡음)
      • getset: 조회하고 결과 나오고 치환
      • 옵션: xx/nx
        • xx: 키가 있을 때만 저장(없으면 안 해; 없으면 nil 반환)
        • nx: 키가 없을 때만 저장(없으면 해; 있으면 nil반환)
  • list 순서를 가지는 문자열의 목록
    • 리스트 안에 인덱스 있음 reverse index도 있음; 추가되면 인덱스는 알아서 재정리됨  
      • command
        • rpush rpop lpush lpop(return 있음)
          • pop은 조회하고 삭제
        • ltrim 원하는 인덱스가 아니면 다 지움(void)
        • linsert(어디 앞에 넣는다) / lset(지정한 인덱스에 치환) 중간에 넣는 작업
          • 중간에 넣을 때는 O(n)이라 안 빠름
  • hash
    • hset(데이터 넣고 1반환) 
    • field-value 쌍을 가진 아이템의 집합; 데이터 페어를 무제한으로 늘릴 수 있음
    • rdbms의 테이블 데이터와 가장 유사 -> 변환 가능
    • hrandfield 랜덤 / 양수를 주면 겹치지 않게; 음수는 겹쳐도 되게
  • set
    • sadd
    • 중복 안됨
    • 정렬되지 않은 문자열
    • srandmember 랜덤
    • 객체 간 관계 계산(교/차/합/원소개수)
      • sunion 합
      • sinter 교
      • sdiffer 차
  • sortedSet 
    • 스코어 값으로 정렬되는 고유한 문자열의 집합(정렬되어 있음; 매번 정렬할 필요 없음)
    • 모든 아이템은 value-score 쌍
    • 같은 스코어라면 사전순 정렬
    • value는 중복되지 않음
    • 인덱스로 접근 가능(O(logn))
    • -인덱스 사용 가능 나부터 -1
    • command
      • zadd 키 스코어 밸류
      • 옵션
      • xx/nx/lt/gt / withscores(밸류랑 스코어랑 같이 조회)/ rev(역순)/byscore
      • zrange 인덱스 기반으로 데이터 조회
      • zrandmember 랜덤 뽑기
      • bylex(사전순)
        • zrange mySortedSet (b (f bylex
          • (: 포함하지 않고 
          • (b 초과
          • [: 포함하고
  • bitmap
    • 확장된 string형태의 자료구조
    • 2^32개의 비트를 가질 수
    • 저장공간을 줄일 수
    • setbit, getbit, bitcount(1 개수 카운트)
  • hyperloglog
    • 집합의 카디널리티를 추정하는 자료구조
    • 대용량(로그)의 개수 카운팅; 중복제거
    • 12KB 고정용량(엄청 큰 데이터도), 1% 미만의 오차
    • pfadd, pfcount, pfmerge
  • geospatial
    • 위도, 경도 쌍; 지구가 완벽한 '구'라는 전제; 오차가 약간 있음
    • 내부적으로는 sortedSet
    • 특정 위치를 기준으로 검색할 수
    • 반경 몇 미터 안 검색 가능
    • 사각형으로도 조회가능
  • stream
    • 아파치 카프카에서 영향
    • append only 한 key-value형식의 자료구조
    • 메시지 브로커에 사용

key를 관리하는 법

  • 자동으로 생성되고 삭제됨
  • 키가 존재하지 않을 때 아이템을 넣으면 삽입 전 빈 자료구조 생성
  • 모든 아이템을 삭제하면 키도 삭제됨(스트림 예외)
  • 키가 존재하지 않을 때
    • 키를 삭제하는 명령을 하거나;
    • 키에 저장된 아이템을 삭제하거나;
    • 자료구조 크기를 조회하는 read only 커맨드를 수행하면
      • -> 키가 없지만 있는 척; 있고 아이템이 없는 것처럼 동작
  • command
    • 조회
    • keys 명령어는 위험; 다른 요청 blocking 됨;
      • scan 커맨드로 대체가능(여러 번 끊어서 데이터 가져옴)
      • 다음에 조회할 커서를 알려줌 그걸로 연쇄적으로 조회 가능
    • sort, exists, rename/renamenx, copy, type
    • 삭제 flushall, del, unlink
    • 만료시간 expire, expireat, expiretime, ttl

리더보드

  • sorted set: 중복을 허용하지 않고 정렬이 되는 자료구조
  • 데이터입력: ZADD daily-score:220817 200 player:286
  • 랭킹 합산; ZUNIONSTORE weekly-score:2208-3 3 daily-score:220815 daily-score:220816 daily-score:220817 (integer) 4 
  • 최대 다섯 개 까지만 저장 하려면 
    • 검색 기록이 다섯개 이하인 경우 → 삭제 안 함 
    • 검색 기록이 다섯 개보다 많을 경우 → 인덱스 0 삭제
    • 항상 인덱스 -6을 삭제한다면? 오버헤드 감소! 
    • ZREMRANGEBYRANK 사용

캐시로의 레디스

  • 레디스는 빨라, 응답속도를 줄일 수, 자체적인 ha 제공

캐싱 전략

  • 읽기 전략: look aside(lazy loading)
    • 우선 캐시에 데이터가 있는지 확인; 없으면(cache miss) 디비에서 읽고 캐시에 저장
      • 초반에 느릴 수 있음
      • 미리(오픈전) 데이터를 넣어주는 작업을 하기도 하는데 이를 cache warming
    • 캐시가 없더라도 장애로 이어지지 않음
    • 반대로 디비에 몰리면 장애가 날 수도 있음
    • 원본과 동일하도록 유지
      • 디비 업데이트 칠 때 캐시에도 업데이트해야(write through)
  • 쓰기 전략(데이터 일관성)
    • write through(중요하면 동기방식; 별로 안 중요하면 비동기)
      • 항상: redis -> db 업데이트
      • 매번 2개 저장
      • 쓰기 시간이 듦
      • 다시 사용하지 않아도 될 데이터가 이중으로 저장될 수도
      • expire time 설정 추천
    • cache invalidation
      • 디비에 저장할 때 캐시를 삭제
      • 찾을 때 디비에서 가져오고 후에 캐시 업데이트
      • 불일치는 발생하지 않음
    • write behind(나중에 디비에 써; 핫해서 계속 디비 넣기 부하 걸리니; 일정 주기로 동기화)
      • 쓰기가 빈번하다면 
      • 디비에 대량의 write면 디스크 IO -> 성능저하로 이어지기 때문에
      • 캐시에 먼저 업데이트하고
      • 비동기적으로 디비에 업데이트
      • 실시간으로 엄청 정확하지 않아도 될 경우
      • 단, 캐시 날아가면,, 끝

 

레디스를 캐시로 사용할 때 주의할 점

  • 자주 사용하는 데이터 일부만 임시로 저장해야(적은 양)
  • 적절한 메모리를 유지할 수 있도록 적절히 삭제하고 들어오도록 유지해야 함
  • TTL(time to live) 사용은 필수(캐시 유지시간)
    • 메모리 꽉 차면 레디스 자체의 max memory policy에 의해 가장 오래된 키부터 삭제
      • 쓰기를 막는 설정이 기본이긴 한데 이게 더 장애 유발 가능성 그래서 오래된 키부터 삭제하는 정책
      • default는 저장 불가 -> 장애로
      • 자주 사용하지 않는 거 삭제하는 방식으로 설정 변경 필요
  • TTL을 너무 작게 하면 cache stampede 현상
    • cache miss가 날 경우 조회 시간차로 (db) duplicate read, (redis) duplicate write 발생할 수도
  • 캐시로 사용할 경우
    • 영구저장소가 아닌 임시라서 캐시의 백업정책 필수는 아님; 비추
    • 캐시가 없는 경우 서비스장애로 이어진다면 ha구성 필요

메시지 브로커로서의 레디스

메세징 큐

  • 프로듀서 -> -> 컨수머
  • 데이터 푸시
  • 데이터 영속성: 읽으면 큐에서 데이터 삭제
  • 컨수머 추가되면 그 후에 추가된 메시지만 확인가능
  • 1:1

이벤트 스트림

  • 퍼블리셔 -> -> 섭스크리버(구독자)
  • 당겨감
  • 데이터 영속성: 저장소별 설정에 따라 특정기간 동안 저장
  • 구독자 추가되면 이전부터도 확인가능
  • 다:다; 1:다

레디스에서는

  • pub/sub
    • 최소한의 메시지 기능
    • 클러스터에서도 사용가능
    • 한번 채널에 전파되면 사라져; 일회성
    • 메시지가 잘 갔는지 모름(보관 안 함)
    • end-end에서는 별로
    • notification 딱 보내고 끝이면 괜찮음
    • command
      • subscribe / publish
  • list를 이용한 메시지 큐
    • list.exists
    • rpushx 이미 캐싱되어 있는(존재하는) 경우에만 입력(불필요한 리소스 줄일 수)
    • event loop 
      • 폴링: 이벤트 큐에서 확인 -> 핸들러
      • 즉각적인 확인 X, 주기별로 체크
      • 리스트에서 blocking을 추가하면 큐확인을 기다릴 필요 없음
      • brpop / blpop -> 있음 반환; 없으면 새로 올 때까지 기다렸다가 반환
      • circular queue: rpoplpush
  • stream 자료구조
    • 연속적으로 계속 들어오는 데이터 처리
    • 써도 사라지지 않고 남아있음
    • 카프카처럼 사용가능
    • 로그를 저장하기 적절
      • append only; 중간에 저장하지 않음
    • range 검색가능, tail 가능, 그룹핑 가능
    • xadd 
      • command에 "*" : 시간 millisec을 timestamp로 갖겠다,

데이터 영구적으로 저장하는 법

  • 재시작하면 데이터 날아감
  • 서버에 파일로 저장함
  • AOF: 커맨드 자체 저장; 과정을
    • 파일이 커지는 걸 막기 위해 aof는 bgrewriteaof로 파일을 다시 써서 압축
  • RDB: 데이터의 최종 스냅샷 저장(메모리 자체); 결과만
    • bgsave 커맨드로 새로운 스냅샷 저장
  • 이때 백그라운드 프로세스를 생성하기 때문에 메모리 초과로 인한 장애 발생 가능성 매우 큼
  • 비추

레디스 HA(high availability)

고가용성, 안정성 = 사용시간/전체시간

  • 복제: 마스터 -> 복제본 실시간 복사
  • 자동 failover: 마스터 노드에 발생한 장애를 감지해서 연결을 복제본 노드로 리디렉션 하도록; 수동으로 안 해도 됨

replication

  • master-replica
  • 마스터는 하나; 다중 마스터 불가(지원 안 함)
  • 마스터 노드는 rdb파일을 생성하여 리플리카 노드에 전달
    • 만드는 중에 메모리 증가
  • 리플리카에서 replicaof 실행
  • 쓰기는 마스터에서만
  • 장애 시 자동 failover 안돼서 잘 안 씀(커넥션 정보 수동으로 설정 변경해 줘야)

sentinel

  • ifnot: 복제 구성 시 장애 발생하면 직접 레디스 엔드포인트 변경 필요
    • replica of no one(복제본으로 활동하지 않도록) 설정하고 설정 변경 후 재시작
  • 데이터를 저장하지 않고 모니터링만 하는 프로세스(최소 3대 필요; 과반수가 필요; 홀수 구성)
  • 같이 설치됨; 추가로 다운로드할 필요 없음
  • 정상적으로 동작하기 위해선 최소 세 대의 센티널 프로세스가  필요
  • 마스터 파악; 마스터로 직접 연결 -> 변경되면 클라한테 알려줌
  • 마스터가 정상적으로 동작하는지 판단할 때 쿼럼(과반수) 이상일 때 페일오버 
  • 새로운 마스터가 되면 그동안의 데이터를 모두 날린 후 새로운 데이터를 복제받음
  • 다운된 마스터가 살아나면 새로운 마스터에 복제본으로 연결됨

cluster

  • full mesh 구조; 서로서로 감시(최소 3대, replica까지 치면 6대 필요)
  • 스캐일 업; 수직 확장: 스펙업
  • 스캐일 아웃; 수평 확장: 개수 증가
  • 일반적으로 업을 먼저 하고 아웃을 해
    • 키가 차있으면 먼저 메모리를 올려 스캐일 업
    • 메모리 문제가 아니라 처리량 문제면 스캐일 아웃 -> 처리량이 많아짐; 병렬도 가능; 마스터도 많아질 수
  • 데이터 샤딩
    • 개발(애플리케이션)에서 신경 쓰지 않아도 됨
      • 클러스터 아무 곳으로 던지면 알아서 리디렉션
    • 클라이언트 -> 클러스터 맵에 키랑 어디에 있는지 매핑 정보 들고 있음
      • 1 키 - 1 마스터
    • full mesh구조
      • 모든 마스터, 리플리카 노드는 가십 프로토콜을 사용해 서로서로 통신
      • 최소 세 개의 마스터 노드 필요
    • 샤딩 방법
      • 모든 키는 해시 슬롯에 연결됨(최대 16384개; mod 16384)
      • 해시 슬롯을 마스터 노드가 나눠가짐(나눠서 저장됨)
      • 키가 어떤 마스터에 저장되어 있는지 해시 함수로 알 수 있음(저장; 조회 모두 사용)
    • 마스터 노드 추가/삭제
      • 카프카는 데이터 이동 시 해당 데이터 사용 불가한데(전체 블라킹)
      • 레디스는 키를 새 마스터 옮기더라도 하나씩 옮기기 때문에 다운타임이 안 길어
      • 간편한 편.. 

레디스 도입 시

  • 어떤 용도?(persistence 기능 사용 유무)
    • 캐시
      • 저장 기능을 사용하지 않도록(원본이 디비에 있으면)
      • 캐시가 죽어도 애플리케이션에 영향가지 않도록(look-aside , write-through)
    • 디비
      • sentinel 사용
      • 애플리케이션 죽으면 영향 갈 수 있음
      • aof 사용하는 것이 안전
        • 주기적으로 rewrite 되도록 파라미터 조절 필요

레디스 구성을 할 때 미래를 생각하여 데이터를.. 짜야한다.

싱글 했다가 중간에 cluster로 바꿨는데 미리 염두에 두고 작업해야.. 나중에 cluster 옮겼는데 일부 명령어 안되고 잘 안될 수도 있다.

 

메모리 관리

  • used_memory: 논리적으로 Redis가 사용하는 메모리
  • used_memory_rss: OS가 Redis에 할당하기 위해 사용한 물리적 메모리 양
  • 삭제되는 키가 많으면 fragmentation 증가
  • 특정 시점에 피크를 찍고 다시 삭제되는 경우
  • TTL로 인한 eviction이 많이 발생하는 경우
  • 파편화 된 데이터 정리 해주는 명령어
    • CONFIG SET activedefrag yes

 

del 명령어보다 unlink

728x90
반응형

'개발 > cache' 카테고리의 다른 글

[redis] sorted set  (1) 2024.12.16
분산락 - redis 사용  (0) 2024.11.08

+ Recent posts