몽수의 Redis 알아보기
What is Redis?
- Redis는 데이터베이스다. 사용자 계정, 블로그 게시물, 댓글 등 앱의 온갖 정보를 저장하는 데 사용된다.
- 저장한 정보를 나중에 쿼리해 가져올 수 있다.
→ 이러한 점은 다른 데이터베이스와 같다.
그럼 다른 데이터베이스가 아니라 Redis를 사용하는 이유는?
💡 레디스는 빠르다!
레디스가 빠른 이유 3가지
1. 모든 데이터가 메모리에 저장된다.
- 대부분의 데이터베이스는 정보를 컴퓨터의 메모리와 하드 드라이브에 저장
- 메모리의 데이터는 빠르게 액세스 할 수 있지만 하드 디스크의 데이터를 액세스하는 건 비교적 느리다.
- 레디스는 하드 디스크에 정보를 저장하지 않고 모든 데이터를 메모리에 저장 → 그래서 비교적 빠르게 접근
그렇다고 항상 좋은건 아님
→ 컴퓨터의 메모리 크기보다 더 큰 데이터셋을 가지고 있으면 작업하기 어렵다
ex) 데이터셋의 크기가 100GB인데 컴퓨터의 메모리 크기가 8GB라면 메모리에 다 넣을 수 없음
2. 모든 데이터를 아주 단순한 구조로 관리한다.
레디스의 모든 데이터는 연결 리스트, 정렬 세트, 해시 맵과 같은 자료 구조로 관리된다.
3. 레디스는 아주 단순하다.
- PostgreSQL이나 MySQL과 같은 데이터베이스는 사용하기 쉽도록 다양한 기능이 있다.
- 트리거, 스키마, 외래키 제약 조건, 유니크 제약 조건, 트랜잭션 롤백
- 하지만 기능이 추가된 만큼 성능이 저하된다.
↔
- 레디스는 다르게 접근해서 다양한 기능이 추가되지않아 아주 단순하다.
기본 명령어 - String
SET message 'Hi there!' // INSERT
// message라는 키가 생성
// message라는 값에는 'Hi there'값 할당
GET message
// message에 할당된 value값을 가져온다.
SET
”키 또는 변수 이름” ‘할당할 값”
GET
문자열을 가져올 수 있음
MGET
: 하나의 명령어에서 여러 값을 가져올 수 있다.
MSET
: 하나의 명령에서 여러 값을 설정할 수 있다.
DEL
: 해당 키와 저장된 데이터를 함께 삭제 해준다.
GETRANGE
: 데이터베이스 내 존재하는 문자열에서 특정 범위 문자만 가져올 수 있다.
- ex) 인덱스 0 ~ 3까지 값 가져오기GETRANGE model 0 2 → “toy”
- GET model → “toyata”
SETRANGE
: 기존 문자열의 일부를 업데이트할 수 있다.
- ex) 인덱스 2부터 기존 문자열을 “blue”로 대체
SETRANGE model 2 blue → 결과값 6 : 새로 생성된 문자열의 길이
GET model → “toblue”
숫자 다루기
INCR
: 기존 키에 저장된 숫자에 1을 더 함 → 결과값을 반환해줌
DECR
기존 키에 저장된 숫자에 1을 뺌 → 결과값 반환
INCRBY
: INCR과 기본적으로 같지만 더 할 값을 정함 INCRBY KEY “더할 값”
DECRBY
: DECR과 기본적으로 같지만 뺄 값을 정함 DECRBY KEY “뺄 값”
→ 정수를 다루는 명령어들(소수점이 없는 숫자)
INCRBYFLOAT
: 소수점이 있는 플로트 값 처리
- 빼기를 하려면 음수 넣기
Key Naming
- 키는 고유한 이름을 가져야 한다.
- 다른 개발자가 키 이름을 보거나 디비에서 데이터를 봤을 때 무슨 역할을 하는지 이해할 수 있어야 한다.
- 키 이름을 작성할 때 오타가 발생하는 것을 막기 위해 키 이름을 생성하는 함수를 사용한다.
어떤 이름으로 지어야 좋을까?
- 키에 콜론을 넣어 여러 부분으로 나눈다.
- 저장되는 데이터 타입 : 고유한 식별자user:45 → ID가 45인 사용자의 정보가 담긴 키
- users:posts:901 → 사용자가 생성한 게시물 중 ID가 901
- ex)
- 고유 아이디 앞에는: 대신 #을 쓰는 관례가 있음ex)
- user#45, items#45, users:posts#901
- → 나중에 검색을 편하게 하기 위해서
Hash
: 중첩된 키 값 쌍의 모음을 지정할 수 있다.
HSET
: Redis에 해시를 생성하고 저장하는 명령어
- 첫번째 인수는 해시 자료 구조를 저장할 키 이름
- 첫 번째 인수 다음에는 키 이름과 값을 반복적으로 작성
- ex) HSET company name ‘Concrete Co’ age 1915
- 업데이트 또한 가능하다.
- ex) HSET company name ‘Concrete Co’ age 1915 industry meterials revenue 5.3 → 결과값 2( 2개의 행만 업데이트 )
HGET
: 해시에서 하나의 필드를 가져올 수 있다.
127.0.0.1:6379> HGET company name
"Concrete Co"
HGETALL
: 해시에 저장되어 있는 서로 다른 모든 키-값 쌍을 가져온다.
127.0.0.1:6379> HGETALL company
1) "name"
2) "Concrete Co"
3) "age"
4) "1915"
5) "industry"
6) "meterials"
7) "revenue"
8) "5.3"
HEXISTS
: 기존 해시에 키가 정의되어 있는지 확인한다.
ex ) HEXISTS company age
→ company에 저장된 해시에 age가 있다면 1, 없다면 0 반환
DEL
: 문자열의 명령어와 동일하게 작동하며 해당 키에 저장된 해시 전체를 삭제한다.
HDEL
: 해시에 저장된 키-값 쌍 하나 삭제
HINCRBY
: 해시내의 필드값을 찾아 정수값을 더해준다.
HINCRBYFLOAT
: 해시내의 필드값을 찾아 실수값을 더해준다.
→ HINCRBY
, ~FLOAT
공통 : 존재하지 않는 키에 실행하면 키가 생성되고 value값이 들어간다.
→ 빼고 싶다면 음수를 넣어주면 된다.
HSTRLEN
: 해시에 저장된 문자열의 길이를 반환
→ ex ) HSTRLEN company name → company의 name필드의 길이
HKEYS
: 해시의 모든 키를 가져온다.
ex ) HKEYS company → company의 모든 키 가져온다.
HVALUES
: 해시의 모든 키에 대응하는 필드값을 가져온다.
ex) HVALUES company → company의 모든 키에 대응하는 필드값을 가져온다.
주의해야하는 점
await client.hSet('car', {
color: 'red',
year: 1950,
engine: { cylinders: 8 },
owner: null,
service: undefined
});
// HSET car color red year 1950
const car = await client.hGetAll('car');
console.log(car);
[INFO] 18:16:10 Restarting: /Users/kimyongsu/Downloads/redis/rbay/sandbox/index.ts has been modified
TypeError: Cannot read properties of null (reading 'toString')
at pushObject (/Users/kimyongsu/Downloads/redis/rbay/node_modules/@node-redis/client/dist/lib/commands/HSET.js:40:47)
→ 이런 오류 발생
이유는 owner
필드의 null값 때문이다.
HGETALL 메서드의 동작 방식
- HGETALL 메서드는 오브젝트 안의 키값과 안의 값을 하나씩 확인해서 toString() 메서드를 호출한다. → 여기서 문제가 발생
- owner의 값이 null이므로
null.toString()
을 호출한다.