Redis 특징
- 고성능 키-값 저장소로서 문자열, 리스트, 해시, 셋, 정렬된 셋 형식의 데이터를 지원하는 NoSQL
- 단순 캐시 서버로 인식해서는 안된다.
- Memcached 와 동일한 기능을 제공하지만 영속성, 다양한 데이터 구조와 같은 부가적인 기능을 지원하기 때문이다.
- 모든 데이터를 메모리에 저장하고 조회(인메모리 데이터베이스 솔루션)
- 읽기 성능 증대를 위해 서버 측 복제(replica) 를 지원
- 쓰기 성능 증대를 위해 클라이언트 측 샤딩 지원
- 키-값 저장소로 문자열, 리스트, 해시, 셋, 정렬된 셋과 같은 다양한 데이터형 지원
- NO SQL 특징
- https://devhtak.github.io/no%20sql/2021/10/10/01_MongoDB_NoSQL.html 참고
- 장단점
- 성능
- 모든 Redis 데이터는 메모리에 저장되어 대기 시간을 낮추고 처리량을 높인다.
- 평균적으로 읽기 및 쓰기의 작업 속도가 1ms로 디스크 기반 데이터베이스보다 빠르다.
- 유연한 데이터 구조
- Redis의 데이터는 String, List, Set, Hash, Sorted Set, Bitmap, JSON 등 다양한 데이터 타입을 지원한다.
- 따라서, 애플리케이션의 요구 사항에 알맞은 다양한 데이터 타입을 활용할 수 있다.
- 개발 용이성
- Redis는 쿼리문이 필요로 하지 않으며, 단순한 명령 구조로 데이터의 저장, 조회 등이 가능하다.
- Java, Python, C, C++, C#, JavaScript, PHP, Node.js, Ruby 등을 비롯한 다수의 언어를 지원한다.
- 영속성
- Redis는 영속성을 보장하기 위해 데이터를 디스크에 저장할 수 있다. 서버에 치명적인 문제가 발생하더라도 디스크에 저장된 데이터를 통해 복구가 가능하다.
- 싱글 스레드 방식
- Redis는 싱글 스레드 방식을 사용하여 한 번에 하나의 명령어만을 처리한다. 따라서 연산을 원자적으로 처리하여 Race Condition(경쟁 상태)가 거의 발생하지 않는다.
- 하지만, 멀티 스레드를 지원하지 않기 때문에 시간 복잡도가 O(n)인 명령어의 사용은 주의해서 사용해야 한다.
Redis 시작
- 레디스와 데이터 구조
- 레디스는 거대한 키-값 저장소로 거대한 맵(Map) 저장소이다
- 키 하나에 데이터 형 하나가 저장되어 있는 단순한 구조로 이것이 레디스의 큰 장점이자 단점이다
- 장점은 직관적이지만 단점은 저장된 데이터를 가공하는 방법에 제한이 있다는 것
- 레디스 데이터 구조와 명령어
- 문자열 데이터
- 저장가능한 최대 문자열 길이는 512MB 로, 크기가 넘어가는 경우 Error 발생
- 레디스가 문자열 데이터를 저장할 때는 인코딩된 문자열과 몇가지 부가정보가 포함된 구조체로 변환하여 저장
- 문자열 데이터의 입력과 조회
- mset/mget: multi set or get (O(N) - N 개는 저장/조회 키 수)
- getset: 키에 대한 값이 있으면 조회/ 없으면 저장(O(1))
- incrby/decrby: 숫자의 증가와 감소 (O(1))
- setbit/getbit: 비트연산(O(1))
- strlen/bitcount: 문자열/비트 길이 조회(O(1))
- 해시 데이터
- 해시 데이터는 문자열 필드와 값으로 이루어진 맵 구조
- 해시 데이터에는 2^32 - 1 개(42억개)의 필드와 값을 저장할 수 있다
- 그룹데이터 저장
- hmset: 주어진 필드와 값의 쌍을 해시 데이터에 저장 (O(1)
- hsetnx: 주어진 필드가 존재하지 않을 때 저장, 존재한다면 값을 저장하지 않는다 (O(1))
- hmget: 주어진 필드 목록을 주어진 키에 조회 (O(1))
- hlen: 주어진 키에 저장된 필드의 개수 조회(존재하지 않으면 0, O(1))
- hdel: 주어진 키에 저장된 필드를 제거(O(1))
- 숫자의 증감(해시에 저장된 데이터의 필드값이 숫자일 때)
- hincrby: 주어진 키에 저장된 필드에 숫자 증감처리(O(1))
- hincrbyfloat:: 주어진 키에 저장된 필드에 숫자 증감처리(float, O(1))
- 해시 데이터의 키 목록 조회
- hkeys: 주어진 키에 저장된 모든 필드 목록 조회(O(N))
- hvals: 주어진 키에 저장된 모든 값에서 필드 이름을 제외한 값의 목록 조회(O(N))
- 셋 데이터
- 중복을 허용하지 않는 집합 형태의 자료구조로 정렬되어 있지 않다.
- 셋 데이터에는 2^32 - 1 개의 값을 저장할 수 있다
- 집합 연산
- sinter: 주어진 키에 저장된 요소들의 교집합을 돌려준다(O(N) - N은 가장 적은 수의 요소를 가진 셋에 저장된 요소 수)
- scard: 주어진 키에 저장된 요소들의 개수를 돌려준다(O(1))
- srem: 주어진 키에 저장된 요소를 제거하고 제거된 요소의 개수를 돌려준다(O(1))
- spop: 주어진 키에 저장된 요소 중에 임의의 요소를 제거하고 제거된 요소를 돌러준다. 키가 없으면 nil을 돌려준다(O(1))
- sismember: 입력된 요소가 주어진 키에 저장되어 있는 지 검사. 존재하지 않으면 0을 돌려준다(O(1))
- smove: 원본키에 저장된 요소를 대상키로 이동하고 이동 결과를 돌려준다 (O(1))
- 정렬된 셋 데이터
- 셋 데이터와 동일한 특징을 가지면서 요소 정렬이라는 부가적인 특징을 갖는다
- zadd key 가중치 value: key에 대하여 정렬된 셋 데이터를 저장하며 가중치를 정할 수 있다
- zrevrange: 주어진 키에 저장된 요소들의 내림차순 정렬 순서 범위에 해당하는 요소 조회(O(log(N) + M))
- 가중치 변경
- 아이템의 가중치를 새로 지정하는 방법 외에 증가/감소 시킬 수 있다
- zincrby: 주어진 키에 저장된 셋 데이터 중 지정된 요소의 가중치를 입력된 값만큼 증가(O(log(N)))
- zrank: 주어진 키에 저장된 셋 데이터 중 지정된 요소의 순위 조회(O(logN))
- zrank key value : 가중치 조회
- zrevrank: 주어진 키에 저장된 셋 데이터 중 지정된 요소의 순위 조회(O(log(N))
- zreverange key startIndex endIndex: value 들 조회
- zrange:: 정렬된 셋의 범위 데이터를 오름차순으로 조회
- zrangebyscore: 정렬된 셋의 점수 범위에 해당하는 데이터 조회
- zremrangebyrank: 정렬된 셋에서 순위에 해당하는 범위의 데이터 제거
- zremrangebyscore: 정렬된 셋에서 가중치에 해당하는 범위의 데이터 제거
- zrevrange: 정렬된 셋의 범위 데이터를 내림차순으로 조회
- 순위 처리와 조회
- zscore: 주어진 키에 저장된 셋 데이터 중 지정된 요소의 가중치 조회 (O(1))
- zrevrangebyscore: 정렬된 셋에 저장된 데이터의 가중치 범위에 해당하는 요소의 목록 조회 (O(logN))
- 정렬된 셋 명령의 특별한 표현식
- zcount: 가중치 범위의 값에 해당하는 요소의 개수를 조회
- zrangebyscore: 가중치 범위의 값에 해당하는 요소의 목록을 오름차순으로 조회
- zremrangebyscore: 가중치 범위의 값에 해당하는 요소 제거
- zrevrangebyscore: 가중치 범위의 값에 해당하는 요소의 목록을 내림차순으로 조회
- 리스트 데이터
- 저장 순서를 기억하는 데이터 구조로 중복 허용
- 2^32 - 1 개 저장 가능
- 내부적으로 덱 구조를 구현하고 있으며 스택과 큐의 특징을 하나로 모은 자료구조
- 스택 연산
- lindex 키: 키 조회 인덱스 (O(N))
- rpop 키: 키에 저장된 요소 중 맨 오른쪽 요소 조회 (O(1))
- blpop 키 만료시간: 리스트에 저장된 요소 중 맨 왼쪽 요소 조회(O(1))
- brpop 키 만료시간: 저장된 요소 맨 오른쪽의 요소 조회
- 큐 연산
- lpush key value / rpush key value
- lpop key value / lpush key value
- lrange key startIndex endIndex / rrange key startIndex endIndex
- lindex key index
- 블로킹 조회
- 어떤 연산이 특정 조건이 될 때까지 대기하는 것
- blpop brpop brpoplpush
- 키 관리
- del key : 저장된 키와 값 삭제 (O(1))
- rename 변경할key 변경될key: (O(1))
- expire key 만료시간: 지정된 키에 만료시간을 초 단위로 설정 (O(1))
- ttl key: 지정된 키의 남은 만료시간을 초단위로 조회 (O(1))
- exists key: 키가 존재하는 지 확인 (O(1))
- expireat key ‘unix timestamp’: 만료시간 설정 (O(1))
- persist key: 지정된 키의 만료시간을 없앤다
- keys: 키 목록 조회
- 레디스 키 설계
- NoSQL에 단순성을 해치지 않으면서 정보를 효율적으로 저정할 수 있는 방법이 키 설계이다.
- 키에 의미를 부여하기 위해 콜론 기호를 사용
- 키를 설계하는 방법
- 관계형 데이터베이스의 스키마를 기본으로 하여 레디스의 저장구조로 바꾸는 방법
- User 테이블(사용자번호,이름) / Posting 테이블(사용자번호, 작성글번호, 제목, 내용,작성일자)이 1:N 구조로 RDBMS 스키마가 정의되어 있다면
- 레디스에서는 작성글:사용자번호:작성글번호 를 키값으로 제목/내용/날짜가 저장된 해쉬데이터 구조로 저장할 수 있다.
- key: posting(작성글 테이블):11452(사용자번호):151(작성글번호)
- 화면에 출력될 기준으로 하여 키를 설계하는 방법
- 두 방법 모두 키에 부가적인 정보를 포함한다
레디스 클라이언트
- 레디스는 http rest와 같은 범용 프로코콜을 사용하지 않고 전용 프로토콜을 사용하여 서버와 통신한다
- 레디스 클라이언트 라이브러리를 사용하면 된다
- 프로토콜 구조
- 전송 프로토콜
```
- 인자 개수 CRLF
$ 첫번째 인자의 개수 CRLF
인자 CRLF
…
$ N번째 인자의 개수 CRLF
인자 CRLF
```
- 수신 프로토콜
- 첫번째 바이트가 응답 데이터 종류를 의미
- 응답 데이터 종류에 따라서 응답 프로토콜의 구조가 달라진다
```
- 상태응답
-
- 에러응답
- 숫자응답
$ 단일벌크응답
- 멀티벌크응답
```
- 대량의 데이터 입력
출처
- 이것이 레디스다 초고속 읽기 쓰기를 제공하는 인메모리 기반 NoSQL, Redis: 한빛미디어, 정경석 저자