Infra

몽수의 Redis 알아보기

기몽수 2024. 7. 20. 16:50

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

  1. 키는 고유한 이름을 가져야 한다.
  2. 다른 개발자가 키 이름을 보거나 디비에서 데이터를 봤을 때 무슨 역할을 하는지 이해할 수 있어야 한다.
  3. 키 이름을 작성할 때 오타가 발생하는 것을 막기 위해 키 이름을 생성하는 함수를 사용한다.

 

어떤 이름으로 지어야 좋을까?

  • 키에 콜론을 넣어 여러 부분으로 나눈다.
  • 저장되는 데이터 타입 : 고유한 식별자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()을 호출한다.