본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

 

 

 

강의 요약

오늘은 Redis의 핵심 컬렉션 데이터 타입 중 List, Set, Hash에 대해 학습했다. 주로 연산자 종류와 간단한 실습 내용만 존재하여 각 타입의 개념과 내부 구조, 주요 연산자의 시간 복잡도, 그리고 실무에서 주의해야 할 점들을 추가적으로 학습 및 정리해보았다.

 

 

List 타입

List는 양방향 삽입/삭제가 가능한 순서형 컬렉션이다. FIFO(Queue) 또는 LIFO(Stack) 구조로 활용할 수 있으며, 동일한 키에 여러 값을 순차적으로 저장한다.

 

내부 구조

  • List는 quickList라는 자료구조로 구현되어 있다.
    • quickList는 이중 연결 리스트(Doubly Linked List)의 각 노드가 작은 압축 리스트를 담고 있는 하이브리드 구조다.
  • Redis 7.0부터 ziplist가 listpack으로 대체되었다.
    • listpack은 각 노드의 길이를 노드 끝에 배치하여 ziplist의 연쇄 업데이트 문제를 완전히 해결했다.
  • 연속된 메모리 블록을 사용하기 때문에 CPU 캐시 효율성이 높고, 작은 데이터에서 메모리 사용량이 적다.
Redis ≤ 6.2 ziplist 연속된 메모리 블록, 중간 삽입/삭제 시 cascading update 발생 가능
Redis ≥ 7.0 listpack ziplist 개선 버전, cascading update 문제 해결, 더 컴팩트한 구조

 

주요 연산 및 시간 복잡도

연산 시간 복잡도 설명
LPUSH / RPUSH O(1) 양 끝 삽입
LPOP / RPOP O(1) 양 끝 제거
LLEN O(1) 길이 조회
LINDEX O(N) 인덱스로 조회
LRANGE O(S+N) 범위 조회 (S: 시작 오프셋, N: 범위 내 요소 수)
LREM O(N+M) 값으로 요소 제거 (N: 리스트 길이, M: 제거된 요소 수)
LSET O(N) 인덱스로 값 수정
LINSERT O(N) 특정 값 앞/뒤에 삽입
  • 리스트의 head or tail에 접근하는 연산은 O(1) 복잡도를 가지며, 매우 효율적
  • 그러나 목록 내 요소를 조작하는 명령어는 일반적으로 O(n) 복잡도를 가진다.
  • LINDEX, LINSERT, LSET 등이 이에 해당하며, 특히 대규모 목록을 처리할 때 이러한 명령어를 실행할 때는 주의가 필요하다.


활용 정리

큐, 로그처럼 순서 있는 데이터 처리에 적합하며 고정 길이 유지도 가능

  • 작업 큐: LPUSH + BRPOP(블로킹 대기)
  • 최근 로그: LPUSH + LTRIM
  • 키 분할: 너무 큰 리스트는 키에 샤딩 값 붙여서 분산 처리
  • 양방향 처리: LPUSH, RPUSH, LPOP, RPOP 모두 O(1)로 매우 효율적

 

 

Set 타입

중복을 허용하지 않는 문자열 집합이다. 순서를 보장하지 않으며 수학적 집합과 유사하다.

삽입, 삭제, 존재 여부 확인이 빠르고 집삽 연산 명령어도 제공된다.

 

내부 구조

모든 버전 hashtable 일반적인 경우
모든 버전 intset 모든 요소가 정수이고 개수가 적을 때
Redis ≥ 7.2 listpack 작은 Set에 대한 공간 효율적 인코딩

 

주요 연산 및 시간 복잡도

연산 시간 복잡도 설명
SADD O(1) per element 요소 추가
SREM O(1) per element 요소 제거
SISMEMBER O(1) 멤버십 확인
SCARD O(1) 요소 개수
SMEMBERS O(N) 전체 요소 조회
SRANDMEMBER O(N) N개 랜덤 요소 (count 지정 시)
SPOP O(N) N개 랜덤 제거 (count 지정 시)
SINTER O(N*M) 교집합 (N: 가장 작은 Set 크기, M: Set 개수)
SUNION O(N) 합집합 (N: 모든 Set 요소 합)
SDIFF O(N) 차집합 (N: 모든 Set 요소 합)
SSCAN 각 호출마다 O(1),  완전한 반복에는 O(N) 멤버들을 반복하여 조회
  • 대부분의 집합 연산(추가, 제거, 집합 원소 여부 확인 등)은 O(1) 시간 복잡도를 가지며, 매우 효율적
  • 그러나 수십만 개 이상의 원소를 가진 대규모 집합의 경우 SMEMBERS 명령어 실행 시 주의가 필요하다.
    • O(n) 시간 복잡도를 가지며 단일 응답으로 전체 집합을 반환
    • 대신 SSCAN 사용 혹은 SCAN + SSCAN 조합을 활용하는 것이 좋다.

활용 정리

중복없는 집합 표현과 집합 연산 기능을 활용해 간단한 필터링과 샘플링 가능하다.

  • 중복 제거: 자동으로 동일 값 제거
  • 태그 필터링: 교집합으로 조건 필터 구현
  • 랜덤 추출: SRANDMEMBER 활용
  • 키사이즈 주의 필요

 

 

Hash 타입

한 키안에 여러개의 필드-값 쌍을 저장하는 자료구조다. 일반적인 해시맵과 유사하지만 레디스에서는 복수 필드를 하나의 키 아래에 묶는 용도로 사용한다. 

 

내부 구조

모든 버전 hashtable 일반적인 경우
Redis ≤ 6.2 ziplist 공간 효율성이 좋으며 작은 해시에 적용
Redis ≥ 7.0 listpack 공간 효율성이 좋으며 작은 해시에 적용

 

주요 연산 및 시간 복잡도

연산 시간 복잡도 설명
HSET O(1) 필드 설정
HGET O(1) 필드 조회
HMSET / HMGET O(N) 다중 필드 설정/조회 (N: 필드 수)
HDEL O(N) 필드 삭제 (N: 삭제할 필드 수)
HEXISTS O(1) 필드 존재 확인
HLEN O(1) 필드 개수
HGETALL O(N) 전체 필드-값 조회
HKEYS / HVALS O(N) 전체 키/값 조회
HINCRBY O(1) 정수 필드 증가
  • 대부분의 해시 명령어는 O(1)
  • HKEYS, HVALS, HGETALL 및 대부분의 expiration-related 명령어와 같은 일부 명령어는 O(n)이며 주의가 필요하다.
    • 마찬가지로 HGETALL 대신 HSACAN 권장

 

활용 정리

하나의 키에 여러 필드를 저장할 수 있어 객체 저장이나 설정 캐시에 적합

  • 유저/세션 프로필 저장: HSET, HGET
  • 소형 객체 최적화: ziplist or listpack 인코딩으로 메모리 절약
  • 필드 수 주의: 필드 수가 많아지면 hashtable로 전환되며 메모리 증가
  • 대량 순회: HSACAN 활용해 점진적 순회 가능

 

참고 출처

 

 

 

시작 시간
종료 시간
학습 인증
수강 인증

 

 

https://fastcampus.info/4oKQD6b

+ Recent posts