[DB] Redis

Kyunghwan Ko·2022년 11월 27일
0

DB

목록 보기
1/1

Redis(Remote dictionary server)

Remote: 원격의

dictionary: Python에서 쓰듯이 key-value 쌍으로 존재

server: 서버

⇒ 외부에 있는 dictionary라는 자료구조를 사용하는 서버 이다 !!

쿠팡에서 모든 물품이 품절로 표시되는 큰 사건이 있었는데,

이 문제는 바로 RedisDB때문이라고 밝혀졌고

그중에서 Redis의 Key값이 너무 많아져서 key가 가질수 있는 최대값인 2147483647(약21억4천7백)을 넘어버렸기때문에 발생한 문제였다.

( 32bit CPU에서 int 최대값이 2147483647(약21억4천7백)이다. )

<실제 쿠팡의 코드 수정사례>

<What is Redis?>

  • Remote dictionary server 이고
  • Database이고, Cache이고, Message Broker이고,
  • In-memory Data Structure Store이다 !!

(In-memory Data Structure Store: 메모리 상에 데이터를 저장하는 구조)

그리고 support rich data structure (다양한 자료구조를 지원한다.)

캐시in-memory 관점에서 설명해보겠다.

Cache

: 나중의 요청에 대한 결과를 미리 저장했다가 빠르게 사용하는 것 → 따라서 CPU에 존재한다 !

원래 DB에 정보가 저장 됫는대 Main Memory에 쉽고 빠르게 접근하면 어떨까 라는 생각에서 등장한 것이 Redis이다.

⭐DB보다 더 빠른 Memory에 더 자주 접근하고 덜 자주 바뀌는 데이터를 저장하자!

== In-memory DB (Cache)이고

이에 대표적인 예가 Redis이다.

자바 vs Redis

자바에서 HashMap쓰면 똑같이 In-memory DB가 구성되는대 왜 자바의 HashMap은 안쓰고

Redis의 Hash를 사용할까?

그 이유는 자바의 경우 다음과 같은 문제점이 있기 때문이다.

  • 서버가 여러대인 경우 Consistency의 문제 발생
  • Multi-Threaded 환경에서 Race Condition 발생

Race Condition

  • 여러개의 Thread가 경합하는 것
  • Context Switcing에 따라 원하지 않는 결과가 발생

Race Condition 해결

  • Redis는 기본적으로 Single Threaded
  • Redis 자료구조는 Atomic Critical Section에 대한 동기화를 제공
  • 서로 다른 Transaction Read/Write를 동기화

=> Redis의 자료구조는 atomic하기 때문에 Critical Section에 대한 동기화를 제공한다.

그렇다면, Redis를 어디서 쓰나요?

  • 여러 서버에서 같은 데이터를 공유할 때 사용
  • Single Server라면? Atomic 자료구조 & Cache 기능을 사용하기 위해 Redis를 사용

주의해야할 점

  • Single Thread 서버 이므로 시간복잡도를 고려해야함
  • In-memory 특성상 메모리 파편화, 가상 메모리 등의 이해가 필요함

Redis가 왜 Single Thread로 동작하는가?

Redis 특징

  • Event Drive(비동기)
  • IO-bound Process
  • Context Switching의 효율이 적다

=> Redis는 CPU연산 보다는 IO처리에 많은 시간을 보내기에 CPU를 Optimization했을 때 효율이 크지 않기 때문이다. 그리고 개발의 단순함, 사용의 단순함을 위해 Redis는 Single Thread방식을 사용한다.

  • Packet으로 하나의 Command가 완성되면 processCommand에서 실제로 실행됨

Redis는 network로 부터 명령을 받아서 처리하는데
이런 command를 형성하고, 처리하는 과정이 single thread이기 때문에
command가 오랜 시간이 걸리는 경우 나머지 요청들이 더이상 받아지지 않고 서버가 다운되는 문제가 발생할 수 있다.
따라서 single thread방식의 경우 시간복잡도(Big-O notation)를 고려해서 효율적으로 처리해야한다.

메모리관리

1. 메모리 파편화

메모리를 할당받고 내놓고 하는(=반환하는) 과정에서 파편화(fragmentation)이 필연적으로 발생한다.

파편화로 인해 Process가 Memory에 올라가려고 할 때, Physical Memory상에 실제 비어있는 총 저장공간보다 더 적게 인식해서 process가 죽어버리는 경우가 발생할 수 있다.

→ Redis사용할때 m을 적당히, 여유있게 사용해야 한다.

2. 가상메모리 swap

실제로 process를 Memory에 올릴때 process 전체를 Memory에 올리지 않고 일부만 Memory에 올려서 사용하고 덜 쓰이는 process는 disk에 저장했다가 필요시 Memory에 올려서 사용하는 방식 사용 → 이때 latency가 발생하게 되고 → single thread 의 환경이기때문에 문제가 발생할 가능성 높음

따라서 swap에 대한 배경지식 필요!, swap을 쓸지/안쓸지 판단 할 수 있어야댐

3. Replication - Fork

Redis는 휘발성이기 때문에 Data가 유실될 가능성 농후 하므로 항상 복제해 놓아야한다.

데이터를 복사해서 slave의 redis서버라든지 disk에 전송해서 저장하는 방식을 사용한다.

복사가 일어날때 fork를 통해 process가 동일하게 복제되는 과정을 거치는데

이 과정에서 Memory공간이 충분하지 않다면 제대로 fork되지 못해서 서버가 죽는현상이 발생할 수 있다.

→ 따라서 fork연산을 할때 주의해야한다. + Memory 을 여유있게 사용해야한다.

Constant Hashing

  • clustering 된 서버에 대해 어떻게 부하를 분산시킬 것인가 에 해당하는 것
  • 그리고 DB를 사용하지 않고 In-memory DB만 사용하는 Data Grid방식을 Spring Germfire, Hazlecast로 제공.

정리

redis의 경우 Java의 HashMap 자료구조의 동시성문제를 해결하기 위해 적용될 수 있습니다. 그리고 redis는 휘발성이기 때문에 데이터가 유실될 가능성이 높아 항상 데이터를 복사해서 별도의 DB에 저장합니다. 이때 redis에서 fork를 통해 프로세스가 복사되는대 이 과정에서 메모리공간에 여유가없다면 fork되지 못해서 서버가 죽는 현상이 있어 fork연산을 할때 주의해야하는 특징이 있습니다.

Reference

https://www.youtube.com/watch?v=Gimv7hroM8A

profile
부족한 부분을 인지하는 것부터가 배움의 시작이다.

0개의 댓글