1. Redis
1) 특징
- Memory Key Value Data Store
- 싱글 스레드로 동작
- 속도가 빠르다
- 고가용성(High Availability)
- 가용성: 사용하고자 할 때 바로 사용할 수 있는 정도
- 복제를 통해 여러 서버에 데이터를 분산 시킬 수 있고 sentinal은 장애 상황을 탐지해서 자동으로 fail-over를 수행
- fail-over: 시스템에 장애가 발생했을 때 예비 시스템으로 업무를 즉시 전환하여 서비스 중단 없이 운영을 유지하는 기술
- 멀티 클라우드: 고가용성
- 하이브리드 클라우드
- 확장성
- 클러스터 모드를 이용하면 쉽게 확장이 가능
- 레디스는 클러스터 내에서 자동으로 샤딩된 후 저장되며 여러 개의 복제본이 생성될 수 있음
- 샤딩: 샤드 단위로 나눈 파티션
- 샤드: 데이터 조각
- 이러한 데이터의 분리는 데이터베이스 레이어에서 처리
- 주요 클라우드 벤더들이 상품화해서 서비스 제공
2) Micro Service Architecture와 Redis
- 데이터 저장소로서의 레디스
- 속도가 빠름
- 레디스는 인메모리 데이터베이스라서 영속성의 문제를 고민해야 함
- AOF(Append Only File)와 RDB(Redis Databade)를 이용해서 주기적으로 파일 시스템에 저장
- Message Broker로 활용 가능
- Redis에는 pub/sub 기능을 내장하고 있음
- 간단한 알림 서비스에 유용
3) Event Loop를 이용해서 동작
- 주 데이터 저장소로서 사용은 가능하지만 용량이 큰 데이터 저장소로는 부적합
- Caching
- 다른 데이터베이스 앞에 배치시켜서 엑세스 지연 시간을 줄이고 처리량을 늘리며 RDBMS나 NoSQL 데이터베이스의 부담을 줄여줌.
- 캐시된 데이터를 한 곳에 저장하는 중앙 집중형 구조를 구성하면 MSA 환경의 수평 확장되는 모든 애플리케이션이 Redis 한 곳만 바라보도록 만들 수 있는데 이렇게 하면 데이터 일관성을 유지할 수 있는 장점이 있음
- 세션 관리
- 게임이나 전자 상거래, 소셜 미디어 등의 세션 관리에 많이 이용
- 실시간 순위표
- Z가 붙는 자료구조들은 점수에 따라 자동으로 정렬해서 저장
- 분산 락
- 공유자원에 대한 락의 관리
- 속도 제한
- 이벤트 속도를 측정하고 필요한 경우 제한할 수 있음
- 대기열
- 채팅 및 메시지
4) Architecture
- Redis Centinel 아키텍쳐는 Redis Centinel, Redis Master, Redis Replica로 구성
- Redis Centinel은 Master와 Replica를 관리하고 평상시 사용되는 서버가 Master이고 Master에 문제가 발생하면 동작하는 서버가 Replica
- 애플리케이션이나 클라이언트는 Redis Centinel에 명령어를 전달하고 Centinel은 명령어가 전달되면 이를 Master에게 질의해서 결과를 얻고 Master가 응답하지 않으면 Replica 중에서 새로운 Master를 선정해서 응답을 받아냅니다.
- Master와 Replica를 묶어서 운영하는 것을 클러스터 모드라고 합니다.
2. 설치 및 접속
1) 설치
- public cloud 서비스 사용
- 직접 설치: https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/
- Windows에 설치
- power shell에 wsl을 설치해서 우분투 방식으로 설치
- docker를 설치해서 컨테이너로 실행
- msi 버전을 다운로드 받아서 설치
- https://github.com/microsoftarchive/redis/releases 로 설치
2) 접속
- 설치 시 제공된 redis-cli를 이용해서 접속
- redis-cli -h <IP 주소> -p <포트번호> -a <패스워드>
- IP 주소는 생략하면 127.0.0.1
- 포트번호는 생략하면 6279
- 패스워드는 설정된 경우 사용
3) 데이터 저장 및 조회
- 데이터 1개 저장
- SET 키 데이터
- set "a" adam
- 데이터 1개 읽어오기
- GET 키
- get "a"
- if [get "A"] → (nil)
- 데이터 삭제
- DEL 키
- del "a"
- 데이터 여러 개 저장
- MSET (key) (value) (key) (value)
- mset "a" "adam" "b" "eve"
- 데이터 여러 개 조회
- MGET (key) (key)...
- mget "a" "b"
- 모든 키 조회
- KEYS 패턴
- keys *
- 일정 수의 키를 반복해서 조회
- SCAN (cursor) (pattern) (count)
- scan 0
4) Redis 유효 기간 설정
- Redis에서는 데이터의 유효기간 설정 가능
- 유효 기간이 지나면 메모리에서 데이터를 삭제하기 때문에 사용자의 별도 개입 없이 메모리를 효율적으로 사용 가능
- EXPIRE 명령을 이용해서 설정 (초 단위)
- SET "c" "lee"
- GET "c"
- EXPIRE "c" 30
3. 자료 구조
1) String
- 문자열을 저장하는 자료구조로 512MB까지 저장 가능
- 아이템이 일대일로 저장되는 유일한 자료구조
- 기존 키에 데이터를 저장하면 수정이 됩니다.
- SET hello world
- GET hello
- SET hello redis #데이터수정
- GET hello
- NX를 뒤에 붙여서 없을 때만 저장되도록 할 수 있습니다.
- XX는 이미 존재하는 경우에만 수정하도록 해주는 옵션입니다
- SET hello mongodb NX #키가 없을 때만 저장되므로 저장 안 함
- GET hello
- SET db redis XX #키가 있을 때만 저장되므로 저장 안 함
- GET db
- 숫자도 저장 가능합니다.
- SET counter 100 #숫자 저장
- INCR counter #1 증가
- INCR counter
- INCRBY counter 50 #간격 만큼 증가
- GET counter
2) list
- 순서를 가지는 문자열의 목록
- 최대 43억개의 데이터를 저장하는 것이 가능
- 인덱스를 이용해서 데이터에 직접 접근 가능
- 스택이나 큐로 사용이 됩니다.
- 데이터 삽입은 LPUSH와 RPUSH
- 데이터조회는 LRANGE를 사용하고 시작과 끝 아이템의 인덱스를 각각 인수로 받아서 출력
- 인덱스에 음수를 설정하는 것이 가능하고 음수는 맨 뒤를 의미
- LPOP을 이용하면 첫번째 아이템을 리턴하며 횟수를 지정하면 그 만큼 삭제하고 리턴
- LTRIM은 시작과 끝 인덱스를 받아서 나머지를 모두 제거
LPUSH mylist E
RPUSH mylist B
LPUSH mylist D A C B A #A B C A D E B
LRANGE mylist 0 -1 #전체 데이터 조회
LRANGE mylist 0 3 #A B C A
LPOP mylist #A
LPOP mylist #B
LTRIM mylist 0 1
LRANGE mylist 0 -1
- list(Deque)는 양 끝에 데이터를 넣고 빼는 LPUSH, RPUSH, LPOP, RPOP 은 O(1)로 처리할 수 있으며 인덱스나 데이터를 이용해서 list의 중간 데이터에 접근할 때는 O(n)으로 동작
- LINSERT 명령과 BEFORE와 AFTER 옵션을
LINSERT mylist BEFORE A E #A앞에 E를 삽입
📍[LSET] 데이터 수정
LSET mylist 0 -1
📍[LINDEX] 특정 인덱스의 데이터 조회
LINDEX mylist 2
3) hash
- 필드와 값을 쌍으로 가진 아이템의 집합
- 데이터 추가
- 기본 형식
HSET 이름 키 값 키 값
📍HSET으로 데이터 추가하기
HSET product:123 Name "Happy Things"
HSET product:123 TypeID 35
HSET product:123 Version 2002
HMSET product:123 Name "Track Ball" TypeID 32
📍읽어오기
HGET product:123 Name
HMGET product:123 TypeID Name
HGETALL product:123
#삭제
HDEL procut:123 Name
4) SET
- 정렬되지 않은 문자열의 모임
- 데이터를 중복해서 저장하지 않음
- 집합 관련 연산을 제공
- 데이터 저장은 SADD
# 결과: (integer) 1
SADD myset A
# 중복된 데이터 없어야 함. 결과: (integer) 6
SADD myset A A A C B D D E F F F F G
# 전체 데이터 조회, 순서대로 안 넣어짐
SMEMBERS myset
#랜덤하게 하나 골라서 삭제
SPOP myset
- SUNION, SINTER, SDIFF 명령으로 집합 연산 가능
5) Sorted Set
- 스코어 값에 따라 정렬되는 문자열의 집합
- 스코어와 값을 쌍으로 가짐
- 데이터는 중복없이 저장되므로 set과 유사하며 각 아이템은 스코어라는 데이터에 연결되어 있어 hash와 유사
- 모든 아이템은 스코어 순으로 정렬되어 있어 list 처럼 인덱스를 이용해서 각 아이템에 접근 가능
- list와 sorted set 모두 순서를 갖는 자료구조 이므로 인덱스를 통해서 접근이 가능한데 배열에서 인덱스를 사용하는 것이 일반적이기 때문에 list에서 인덱스를 다루는 것이 빠를 것 같지만 인덱스를 이용해서 아이템에 접근할 일이 많다면 list보다는 sorted set이 효율적입니다.
- list에서 인덱스를 이용해서 데이터에 접근하는 것은 O(n)이지만, sorted set에서는 O(log(n))입니다.
- 데이터 저장
ZADD score:220817 100 user:B
ZADD score:220817 150 user:A 150 user:C 200 user:F 300 user:E
- 옵션
- XX: 존재하는 경우 스코어를 업데이트
- NX: 존재하지 않을 때만 삽입
- LT: 업데이트 하고자 하는 스코어가 기존 아이템의 스코어보다 작을 때에만 업데이트 하는데 기존에 아이템이 존재하지 않으면 삽입
- GT: 업데이트 하고자 하는 스코어가 기존 아이템의 스코어보다 클 때에만 업데이트 하는데 기존에 아이템이 존재하지 않으면 삽입
- 데이터 조회
- 기본적으로 값을 포함하지만 값 앞에 (를 추가하면 제외합니다.
- 최소값과 최대값의 경우에는 값을 직접 입력하지 않고 -inf와 +inf를 이용합니다.
ZRANGE key start stop
#인덱스로 조회
ZRANGE score:220817 1 3 WITHSCORES
#스코어로 조회
ZRANGEBYSCORE score:220817 100 150 WITHSCORES
6) Bitmap
- string 자료구조에 bit 연산을 수행할 수 있도록 확장한 형태
7) Hyperloglog
- 집합의 원소 개수인 카디널리티를 추정할 수 있는 자료구조
- 대량의 데이터에서 중복되지 않는 고유한 값을 집계할 때 유용하게 사용할 수 있는 자료구조
- set은 중복을 피하기 위해서 저장된 데이터를 모두 기억하고 있지만 hyperloglog는 입력되는 데이터 자체를 저장하지 않고 자체적인 방법으로 데이터를 변경해서 처리합니다.
- 실제 데이터를 전부 기억하지 않기 때문에 효율적
- 카디널리티 추정 오차는 0.81% 정도 발생
PFADD members 123
PFADD members 500
PFADD members 123
PFADD members 12
PFCOUNT members
8) Geospatial
- 경도와 위도 데이터 쌍의 집합
- 지리 데이터 저장에 이용
- 내부적으로는 sorted set으로 저장하며 하나의 자료 구조 안에 키는 중복돼서 저장되지 않는다.
GEOADD travel 14.3996 50.0992 Prague
GEOADD travel 127.0016 27.5642 Seoul -122.4345 37.7853 Sanfrancisco
9) stream
- redis를 메시지 브로커로서 사용할 수 있게 하는 자료 구조
- 전체적인 구조는 카프카에서 영향을 받아 만들어져서 카프카에서처럼 소비자 그룹 개념을 도입해 데이터를 분산 처리할 수 있는 시스템
- 데이터를 계속해서 추가하는 방식으로 저장
4. Redis에서 키를 관리하는 방법
1) 키의 자동 생성과 삭제
- stream이나 set, sorted set, hash와 같이 하나의 키가 여러 개의 아이템을 가지고 있는 자료구조에서는 명시적으로 키를 생성하거나 삭제하지 않아도 알아서 생성되고 삭제됩니다.
- 키가 존재하지 않을 때 아이템을 넣으면 아이템을 삽입하기 전에 빈 자료구조를 생성합니다.
# mylist 삭제
DEL mylist
#mylist를 list로 생성하고 1 2 3을 삽입
LPUSH mylist 1 2 3
📍이미 만들어진 자료구조에 다른 자료구조의 명령어를 사용하면 에러가 발생
# String 자료구조
SET hello world
#에러 발생 LPUSH는 list 자료구조에 데이터를 삽입하는 명령
LPUSH hello 1 2 3
📍모든 아이템을 삭제하면 키도 자동으로 삭제되는데 stream은 예외
- 키의 존재 여부는 EXIST로 확인 가능
DEL mylist
LPUSH mylist 1 2 3
EXISTS mylist
LPOP mylist
LPOP mylist
LPOP mylist
EXISTS mylist
- 키가 없는 상태에서 key 삭제, 아이템 삭제, 자료 구조 크기를 조회하면 에러가 아니라 키는 있으나 데이터가 없는 것처럼 동작
DEL mylist
LLEN mylist
LPOP mylist
2) Key 관련 명령
- 존재 여부 확인
EXISTS key [key...]
- 패턴을 가지고 키를 조회
- 키이름 *: 모든 key를 조회
- 키 이름에 ?을 추가하면 1글자의 와일드 카드
- h?llo: hello, hallo 등과 매칭
- 키 이름에 *을 추가하면 글자 수 상관없는 와일드 카드
- h*llo: hllo, hello, haallo 등과 매칭
- [] 안에 나열을 하면 그 중 하나가 됩니다.
- h[ae]llo: hallo, hello 등과 매칭
- ^는 제외하고
- h[^e]llo: hello는 매칭이 되지 않습니다.
- Keys는 위험한 커맨드
- redis에 100만개의 키가 저장되어 있다면 모든 키의 정보를 반환함
- redis는 싱글 스레드 기반이라서 실행 시간이 오래 걸리는 커맨드를 수행하면 다른 모든 커맨드가 차단됩니다.
- 이렇게 오래 걸리는 명령을 redis에 수행하게 되면 다른 클라이언트에서 레디스에 데이터를 저장할 수 없고 그동안 대기열이 늘러날 수 있으며 모니터링 도구가 마스터 노드로 보낸 health check 에 응합할수 없어서 의도하지 않은 fail-over가 발생할 수 있습니다.
- SCAN
- 커서를 기반으로 특정 범위의 키만 조회할 수 있는 커맨드
- SCAN cursor [MATCH parttern] [COUNT count] [TYPE type]
- 리턴하는 값은 다음 cursor의 위치
- 기본적으로 10개의 key만 반환
- SORT
- list, set, sorted set에서만 사용할 수 있는 명령
- 키 내부의 아이템을 정렬해서 반환
- LIMIT 옵션을 이용해서 원하는 개수만큼 반환 가능
- ASC와 DESC를 이용해서 오름차순과 내림차순 설정 가능
- 숫자와 문자열이 섞인 경우 ALPHA 옵션을 사용해서 문자열로 변환해서 정렬 가능
DEL mylist
LPUSH mylist a
LPUSH mylist b
LPUSH mylist c
SORT mylist
LPUSH mylist HELLO
SORT mylist alpha
- RENAME key newkey
SET a apple
RENAME a aa
GET aa
- 키 복제
COPY source destination [REPLACE]
- 키가 존재하면 에러인데 replace 옵션을 사용하면 기존의 키를 지우고
SET B BANANA
COPY B BB
GET B
GET BB
- TYPE
- 자료구조 확인
- TYPE key
- key 전체 삭제
- FLUSHALL [ASYNC | SYNC]
- 키 삭제(동기식)
- DEL 키
- 키 연결 해제(비동기식)
- UNLINK 키
- 키의 만료시간 확인
- TTL 키
- 유효시간이 없으면 -1, 키가 없으면 -2를 반환