레디스 기초 공부

레디스 주요정보 및 특징

  • 영속성을 지원하는 인메모리 데이터 저장소
  • 읽기 성능 증대를 위한 서버 측 복제를 지원
  • 쓰기 성능 증대를 위한 클라이언트 측 샤딩을 지원
  • 5가지 데이터형 (문자열, 리스트, 해시, 셋, 정렬된 셋) 을 지원
  • 메모리 이외의 영구 저장소를 지원하므로 인스턴스 재시작에 대한 캐시 웜업에 대한 고려가 필요하지 않음

기본 명령어

문자열 명령

  • 레디스의 증감처리는 signed integer 로 표현할 수 있는 범위에서만 가능하다(시스템 종속적인 정수형을 가지지 않는다)
    표현범위를 넘어설 경우 overflow 오류 발생
  • 문자열 데이터의 최대 크기는 512MB
커맨드응답지원버전시간복잡도설명
setOK1O(1)주어진 키에 값을 저장한다
append문자열의 전체 길이2O(1)키가 존재하면 append, 아니면 set 과 동일
incr결과값(value)을 리턴1O(1)증가연산 (1씩, 숫자만 해당)
decr결과값(value)을 리턴1O(1)감소연산 (1씩, 숫자만 해당)

리스트 명령

  • 리스트 데이터는 논리적으로 링크드 리스트의 구현이다 (이중 연결 리스트)
  • 데이터가 입력된 순서대로 저장되고 조회된다는 특징 때문에 먼저 입력한 자료를 먼저 처리하는 큐로 사용되기도 한다
커맨드응답지원버전시간복잡도설명
lpush명령이 수행된 후 리스트 사이즈1O(1)맨 앞쪽에 입력된 요소를 저장한다
lrange해당 범위의 요소들, 존재하지 않으면 nilO(S+N)1리스트의 시작 인덱스 부터 종료 인덱스 범위의 요소를 조회한다 (예시)

셋 명령

커맨드응답지원버전시간복잡도설명
sadd성공이면 입력된 값의 개수, 이미 존재하면 01O(N) N은 입력된 값의 개수지정된 셋에 입력된 값을 저장한다.
smembers조회된 값 목록, 존재하지 않으면 nil1O(N) N은 입력된 값의 개수지정된 셋에 저장된 모든 값의 목록을 조회한다.

정렬된 셋 명령

저장된 요소에 가중치를 부여하여 ASC 정렬을 제공한다.
가중치가 동일할 경우에는 정렬 안정성을 보장하지 않는다.

커맨드응답지원버전시간복잡도설명
zadd성공이면 입력된 값의 개수, 이미 존재하면 01.2O(log(N))정렬된 셋에 가중치와 값으로 우리우전 데이터를 저장한다. 단, 이미 존재하는 값이면 기존의 가중치를 입력된 가중치로 덮어쓴다
zrange조회된 값 목록, 값이 존재하지 않으면 nil1.2O(log(N)+M) N은 입력되어 있는 값의 개수, M은 조회된 값으 개수정렬된 셋의 시작 인덱스부터 종료 인덱스 범위에 해당하는 값들을 가중치 오름차순으로 조회한다.

해시 명령

커맨드응답지원버전시간복잡도설명
hset존재하지 않는 필드일 때 1, 존재하는 필드일 때 02O(1)지정된 해시에 요청한 필드와 값을 저장한다
hget지정된 필드가 존재할 때 저장된 값, 아니면 nil2O(1)지정된 해시에 저장된 필드의 값을 조회한다.
hgetall지정된 키에 저장된 모든 필드와 값의 목록2O(N)지정된 키에 저장된 모든 필드와 값을 조회한다.

데이터 처리 명령어

접두사와 접미사

레디스는 기본적인 명령에 접두사와 접미사를 조합한 명령어를 제공한다. (몇 가지 예외 사항은 존재)

접두사 커맨드설명
m멀티
s멀티
z정렬된 셋
h해시 데이터
접미사 커맨드설명
nx값이 없을 경우에만 처리 (원자성 보장)
by주어진 값만큼 증가/감소 처리 (incr, decr 커맨드와 조합하여 사용, 값의 부호에 영향을 받으며 수학적 개념과 동일)

문자열

레디스는 비트연산을 통해 저장되는 문자열 데이터를 비트 단위로 처리할 수 있다.
레디스는 데이터의 저장을 바이트 단위로 하기 때문에 키가 존재하지 않을 때, setbit 의 실행 결과로 생성되는 데이터의 크기는 (오프셋/8) + 1 이다

커맨드응답지원버전시간복잡도설명
getset이전에 저장된 값을 리턴1O(1)입력된 값을 저장하고, 저장되어 있던 값을 리턴한다. 없으면 nil 리턴
setbit이전에 저장된 비트의 값2.2O(1)입력된 오프셋 위치에 저장된 bit 값을 변경한다
getbit비트2.2O(1)입력된 오프셋 위치에 저장된 bit 값을 리턴한다
bitcount지정된 범위에 저장된 비트 중 1의 개수2.6O(N)주어진 키값의 비트 중 1인 값의 개수를 조회한다. 인덱스 범위는 바이트 단위 인덱스다.

해시 데이터

  • 해시 데이터는 232-1개의 필드와 값을 저장할 수 있다 (약 42억)
  • 경험적으로 이해할 수 있는 명령어라 명령어 표는 생략 hmset, hsetnx, hmget, hlen, hdel, hkeys, hvals, hincrby, hincrbyfloat
  • 해시에 저장된 데이터의 필드값이 숫자일 때 증감연산을 이용할 수 있다 (소수점은 17자리로 고정)

해시 데이터의 특별한 유형

셋 데이터

  • 셋 데이터는 232-1개의 필드와 값을 저장할 수 있다 (약 42억)
  • 셋의 특성상 값이 저장될 때 중복에 대한 확인 작업을 수행하기 때문에 nx 접미사 명령은 존재하지 않는다
  • 집합 연산을 지원한다 (합집합, 교집합, 차집합)
커맨드응답지원버전시간복잡도설명
sinter교집합에 해당하는 값1O(N)주어진 키에 저장된 요소들의 교집합을 돌려준다
scard저장된 요소의 개수1O(1)주어진 키에 저장된 요소들의 개수를 리턴한다 (card 는 cardinality 의 약자
srem제거된 값의 수1O(1)주어진 키에 저장된 요소를 제거하고 제거된 요소의 개수를 리턴한다
spop제거된 값1O(1)주어진 키에 저장된 요소 중에서 임의의 요소를 제거하고 리턴한다
sismember존재하면 1, 존재하지 않으면 01O(1)입력된 요소가 주어진 키에 저장되어 있는지에 대한 여부를 리턴한다.
smove이동되었으면 1, 실패하면 01O(1)원본키에 저장된 요소를 대상키로 이동하고 이동 결과를 리턴한다. 원본키가 존재하지 않으면 결과로 0을 리턴하고, 대상 키가 존재하지 않으면 새로운 셋 데이터를 생성하고 요소를 이동시킨다

정렬된 셋 데이터

  • z와 명령어 가운데에 rev 라는 접두사가 추가되면 내림차순 정렬을 의미한다
    zrevrange 명령은 내림차순으로 정렬된 결과를 리턴한다
  • 저장 가능한 요소의 수는 셋 데이터와 동일하다
  • LIMIT 키워드를 이용하여 일부의 데이터만 조회하는 것이 가능하다 MySQL 의 LIMIT 과 유사 (다른 명령어와의 조합도 가능할 것 같은데? 더 공부해봐야겠음)
  • 정렬된 셋의 명령 중에서 가중치의 범위를 인자로 사용하는 명령은 특별한 표현식을 포함하여 사용할 수 있다
    • 무한대 표현식 +inf, -inf
    • 초과/미만 표현식 zrangebyscore ex-key (1 (3 (ex-key 키에 저장된 요소중에 가중치가 1보다 크고 3보다 작은 범위에 해당하는 요소를 조회한다)
커맨드응답지원버전시간복잡도설명
zincrby적용된 가중치 값1.2O(log(N))주어진 키에 저장된 셋 데이터 중 지정된 요소의 가중치를 입력된 값만큼 증가 시킨다
zrank값이 존재하면 가중치 오름차순으로 정렬된 순위, 없으면 nil2O(log(N))주어진 키에 저장된 셋 데이터 중 지정된 요소의 순위를 조회한다. (zero base)
zrevrank값이 존재하면 내림차순 순위, 없으면 nil2O(log(N))주어진 키에 저장된 셋 데이터 중 지정된 요소의 순위를 조회한다. (zero base)
zrangebyscore---정렬된 셋의 점수 범위에 해당하는 데이터 조회
zremrangebyrank---정렬된 셋에서 순위에 해당하는 범위의 데이터 제거
zremrangebyscore---정렬된 셋에서 가중치에 해당하는 범위의 데이터 제거

리스트 데이터

  • 저장 가능한 요소의 수는 셋 데이터와 동일하다
  • 이중 연결 리스트로 구현되어 있기 때문에 첫 번째 요소와 마지막 요소이 조회 시간이 가장 빠르며 리스트의 중간에 저장된 데이터를 조회하는 시간이 가장 오래 걸린다
커맨드응답지원버전시간복잡도설명
lindex해당 인덱스 위치에 저장된 요소1O(N)지정된 리스트에 저장된 요소의 인덱스에 해당하는 요소의 값을 조회한다
blpop조회된 요소2O(1)지정된 리스트에 저장된 요소 중 맨 왼쪽 요소를 조회한다. 단 저장된 데이터가 없거나 키가 존재하지 않을 때는 만료시간에 지정된 시간만큼 대기한다 (단위:초). 0이면 무한히 대기)
brpop조회된 요소2O(1)지정된 리스트에 저장된 요소 중 맨 오른쪽 요소를 조회한다. 단 저장된 데이터가 없거나 키가 존재하지 않을 때는 만료시간에 지정된 시간만큼 대기한다 (단위:초). 0이면 무한히 대기)

키 제어 명령어

레디스 프로토콜

클러스터

복제

프라이머리 노드(쓰기 전용)와 세컨더리 노드(읽기 전용)를 구성하여 트래픽을 분산하는 기법

  • 세컨더리 노드는 언제든지 확장이 가능하다 (데이터 복제 요청을 세컨더리 노드가 프라이머리 노드에게 요청하기 때문에 프라이머리 노드의 무중단이 보장됨)
    단, 세컨더리 노드가 처음 올라올 때 프라이머리 노드의 모든 데이터를 복제해야 하는데 이때 최대한의 리소스를 사용하기 때문에 복제하는 동안에 프라이머리 노드의 성능이 저하될 수 있다.
  • 프라이머리 노드에 쓰기 작업이 발생하면 세컨더리 노드에 변경 이벤트를 전파하여 데이터 일관성을 유지한다.
  • 노드를 복제 한다고 해서 성능이 선형으로 증가하지는 않는다 (데이터 대역폭, 네트워크 대역폭, 데이터 동기화 작업) 이를 임계점이라고 함
  • 레디스 클라이언트에서 쓰기/읽기 노드를 모두 알고 있어야 한다

샤딩

데이터를 특정 조건에 따라 나누어 저장
레디스 2.6 버전은 서버측 샤딩을 지원하지 않기 때문에 위치 투명성이 보장되지 않는다. (클라이언트측 샤딩 기법을 이용해야 함)

  • 수직 샤딩 (Vertical Sharding) 데이터 성격에 따라 분리
  • 범위 샤딩 (Range Sharding) 데이터의 범위에 따라 분리
  • 해시 기반 샤딩 (Hash Based Sharding) 키값을 해싱하고 해싱된 값을 이용하여 저장소를 선택하는 방법으로 일관된 해싱(Consistent Hashing)이라고 부르기도 함

레디스 운영 시 고려사항

레디스는 데이터 저장과 조회에 단일 스레드를 사용한다 (하나의 CPU 코어만 이용), 그렇기 때문에 멀티코어는 레디스 성능에 큰 영향을 주지 않는다.

  • CPU 임계점
  • 메모리 대역폭
  • 네트워크 대역폭

Q. 만약 레디스에 저장될 데이터의 크기를 산정하지 못하여 레디스 설정에서 maxmemory 값을 지정하지 못했다면?
A. 레디스에 데이터가 계속 추가되어 물리 메모리가 부족하게 되면 스왑 메모리를 이용하게 되며 스왑 메모리에 데이터가 저장되기 시작하면 성능이 저하된다
스왑 메모리 공간이 부족해지면 OOM 킬러가 동작한다

레디스가 AOF나 스냅샷과 같은 영구 저장소를 사용하도록 설정되어 있다면 스왑영역은 최소한 물리 메모리 크기만큼의 스왑영역을 설정해야 한다.

레디스에서 스냅샷을 위한 fork 함수가 동작하면 레디스가 점유하는 메모리만큼의 메모리를 다시 할당하려고 시도하게 된다.

레디스 복제 구성에서는 프라이머리 노드의 스냅샷 설정이 꺼져 있더라도, 새로운 세컨더리 노드가 프라이머리 노드에 추가되면 프라이머리 노드는 전체 데이터를 복제하기 위해 스냅샷을 생성한다.
레디스는 복제를 위해서 스냅샷을 생성하고 스냅샷 데이터를 세컨더리 노드로 전송하기 위한 버퍼를 생성하는데, 이 버퍼의 크기가 지정된 크기보다 커지면 세컨더리 노드의 연결을 강제로 끊게 된다.

관련설정 client-output-buffer-limit

기타

  • 레디스의 키 이름에는 제한이 없으며 어떤 문자도 사용할 수 있다 (관례상 콜론은 키에 의미를 부여하는 구분자로 사용된다.)
  • 응답값을 가지는 레디스 명령은 상태응답, 에러응답, 숫자응답, 단일 벌크응답, 멀티 벌크응답으로 나
  • 레디스 명령의 인덱스 표현에서 -1 은 조금 특별하다 (음수가 입력되면 인덱스를 맨 마지막부터 센다.)
    예시)

    lrange key 0 -2 (키의 이름이 key인 리스트의 0번째부터 마지막에서 두번째까지의 데이터를 조회하라)

  • CAP 정리
    일관성(Consistency), 가용성(Availability), 분할 허용성(Partition Tolerance) 모두를 동시에 지원하는 분산 컴퓨터 시스템은 없다
  • 레디스는 정전과 같은 하드웨어 장애 발생 시에 데이터 유실을 방지하기 위하여 AOF(Append Only File) 를 사용한다.
  • https://blog.nahurst.com/visual-guide-to-nosql-systems
  • 해시 데이터의 특별한 유형 레디스는 메모리 공간을 절약하기 위해서 세 가지 내부 저장구조(zipmap, ziplist, intset)를 사용한다.
    이 내부 저장구조를 사용하게 되면 CPU를 더 사용하게 된다.

참고자료

  • 이것이 레디스다 (저자: 정경석 출판사: 한빛 미디어)
Back to Top ↑

댓글남기기