🎲 레디스란?
- Key-Value 구조를 가진 형태로 다양한 형태의 자료구조를 제공하고 데이터를 저장한다
- 레디스 클러스터 모드를 가지고 있어 다중 노드에 데이터를 분산 저장하여 안정성 & 고가용성을 제공한다
- 다양한 목적으로 사용된다 ( e.g. Pub/Sub패턴, 블랙리스트 등등)
- 모든 데이터를 In-Memory인 RAM에 저장하기 때문에 굉장히 빠른 작업 처리 속도를 가지고 있다
- 데이터 영속성을 위한 SSD나 HDD에 저장하는 방식도 사용하고 있다
장점 정리
메모리에 데이터를 저장하면서 매우 빠른 읽기와 쓰기 속도를 보장하고 다양한 데이터 타입을 저장할 수 있다
Redis의 persistence
Redis는 RAM에 데이터를 저장하기 때문에 휘발성 데이터라고 생각하면 된다. 그래서 Redis는 이를 보완하고자 데이터를 디스크에 백업하는 RDB 방식 혹은 AOF방식으로 영속성을 제공한다
- RDB 방식 : 메모리에 있는 데이터 전체에서 스냅샷을 작성하고 이를 디스크로 저장하는 방식이다
- 특정 시간마다 여러 개의 스냅샷을 생성하고, 데이터를 복원해야 한다면 스냅샷 파일을 그대로 로딩만 하면 된다
- 하지만 한번 변경된 데이터는 이후 다시 복구가 불가능하다
- AOF(Append Only File) : 데이터가 변경되는 이벤트가 발생하면 모두 로그에 저장한다
- 데이터를 생성, 수정, 삭제하는 이벤트를 초단위로 취합 및 호그 파일에 작성
- 모든 데이터의 변경 기록들을 보관하고 있기 때문에 최신 데이터 정보를 백업 할 수 있다
- RDB 방식에 비해 데이터 유실의 량이 적다
- RDB보다 로딩이 느리고 파일의 크기가 크다
- 사용방법
- 일부 데이터 손실에 영향을 받지 않는 경우 즉, 캐시로만 사용될때는 RDB
- 장애 상황 직전까지의 모든 데이터가 보장되어야 하는 경우에는 AOF
- 강력한 내구성이 필요하다면 RDB + AOF
🎲 레디스의 스레드
레디스는 사용자들이 실행한 명령어들을 이벤트 루프 방식으로 처리한다. 즉, 클라이언트가 실행한 명령어들을 Event Queue에 적재하고 싱글 스레드를 통해 하나씩 처리한다.
- 장점
- 멀티 스레드가 아니라서 Context switch 가 발생하지 않고 이로 인해 효율적인 시스템 리소스 사용이 가능하다
- Context switch가 발생하지 않기 때문에 데드락또한 걱정이 없다
- 단점
- 오버헤드가 큰 명령어를 처리하는 동안 다른 명령어를 처리 할 수 없다.
- 앞의 명령어를 처리해야 다음 명령어를 처리할 수 있기 때문에 다른 명령어들이 이벤트 큐에 저장되어 있는 시간이 길어진다.
🎲 레디스 자료 구조
- String : 문자열 데이터를 저장 및 조회 할 수 있는 기본 자료 구조이다
- 증감 연산으로 사용도 가능하다 : INCR, INCRBY, INCRBYFLOAT, HINCRBY, HINCRBYFLAOT, ZINCRBY
- Bitmap : 비트 연산을 사용할 수 있다
- List : LinkedList의 형태로 연결되어 있다. 때문에 Push, Pop의 속도가 O(1)이 된다.
- 이를 통해 Queue 와 Stack도 구현 할 수 있다
- Hash : field-value이다. 명심해야한다 Key와 Value가 아닌 Field-Value이다. 이 데이터는 레디스의 키와 매핑되어 있다
- Set : Set 과 매우 흡사하다 중복을 허용하지 않는다 두개의 Set을 비교하는 것도 가능하다
- Sorted Sets : ZSET의 명령어를 통해 사용하며 SET과 비슷한 명령어 이다. 중복을 허용하지 않고 데이터는 스코어와 함께 저장 할 수 있다. 내부적으로 Skip List + HashTable로 이루어져있기에 해당 스코어의 값을 기준으로 정렬하게 되고 만약 값이 같다면 사전 순으로 정렬한다
- Stream : append-only log에 consumer groups과 같은 기능을 더한 자료 구조이다. 카프카와 유사하다 데이터가 수정 삭제는 없고 오로지 추가만 된다.
- XADD events * action like user_id 1 product_id 1
- events라는 큐에 userId 1이 ProductId 1을 좋아요를 눌렀다는 메세지가 담긴것이다.
- HyperLogLog : 집합의 데이터 갯수를 추정할 수 있는 알고리즘이자 이를 사용할 수 있는 레디스의 자료 구조이다. 이 알고리즘은 비트 패턴을 분석하여 비교적 정확한 추정 값을 계산한다 오차는 0.81%만큼 작다 또한 저장 공간이 크지 않아서 카운트에 적합하다
🎲 레디스의 주의 사항
- O(N) 명령어 : 레디스는 싱글스레드이기에 O(N) 명령어처럼 성능의 저하가 일어날 수 있는 명령어는 가급적 피해야한다
- KEYS : 모든 키를 조회하는 것이다 → SCAN 명령어로 대체
- SMEMBERS : Set에 모든 member를 반환, 하나의 Set에 member갯수를 조절하는 것이 좋다
- HGETALL : Hash의 모든 field를 반환한다. 이또한 마찬가지 이다.
- SORT : item을 정렬하는 행위또한 같은 시간 복잡도를 같기에 주의해야한다.
- Thendering herd Problem : 병렬 요청이 공유 자원에 대해서 접근시 급격한 과부하가 발생한다
- Redis에 캐싱되어 있는 데이터가 만료로 인해 사라졌을때 수많은 사용자가 동시에 요청을 한다면 레디스는 이를 DB를 통해 데이터를 가져오게 되는데 동시에 요청을 한 상황이기에 모든 요청이 DB로 몰리게 된다
- 이를 방지하기 위해 캐시를 주기적으로 최신화를 시켜주는 방법을 사용할 수 있다.
- Stale Cache Invalidation : 캐시는 원본이 아니기에 유효성이 손실되거나 변경되었을때 캐시를 변경하거나 삭제해야한다
- 이 또한 캐시를 주기적으로 최신화 시켜주는 방법이 있을 수 있다.
🎲 레디스 특수 명령어
♬ 데이터 만료(Expiration)
- 데이터를 특정 시간 이후에 만료시키는 기능
- TTL(Time To Live)은 데이터가 유효한 시간(초단위)
- 데이터는 조회 요청시에 만료된 데이터는 조회되지 않는다 또한 데이터가 만료되었다고 바로 삭제하지않고 표시만 바꿔주었다가 백그라운드에서 주기적으로 삭제한다.
- 명령어
- EXPIRE greeting 10 ▶ 10초의 만료 시간을 준다
- TTL greeting ▶ 데이터 만료 설정 여부
- SETEX greeting 10 hello ▶ 데이터를 SET으로 꾸미고 10초라는 만료시간을 준다
♬ SET NX/XX
- NX : 해당 Key가 존재하지 않는 경우에만 SET
- XX : 해당 Key가 이미 존재한다면 SET
- Null Reply : SET이 동작하지 않은 경우 (nil)을 응답한다
- 만약 이러한 명령어가 없다면 데이터가 존재하는지 계속해서 확인해야한다
- 명령어
- SET greeting (value) NX ▶ 해당 key가 없다면 OK를 반환하고 value를 SET해준다 하지만 있다면 nil을 반환
- SET greeting (value) XX ▶ 해당 Key가 있다면 OK를 반환하고 value의 내용을 바꾼다 하지만 없다면 nil을 반환
♬ Pub/Sub
- publisher와 Subscriver가 서로 알지 못해도 통신이 가능하도록 decoupling 된 패턴이다
- publisher는 Subscriber에게 직접 메세지를 보내지 않고 Channel에 publish
- Subscriber는 관심이 있는 Channel을 필요에 따라 Subscribe하며 메세지를 수신한다
- Stream 메세지가 보관되는 Stream과는 달리 Pub/Sub는 Subscribe하지 않을 때 발생된 메세지 수신이 불가능 하다
- 명령어
- SUBSCRIBE ch:order ch:payment
- PUBLISH ch:order ner-order
- PUBLISH ch:payment new-payment
♬ Pipeline
- 다수의 commands를 한 번에 요청하여 네트워크 성능을 향상 시키는 기술이다
- Round-Trip Times 최소화 : Requset/Response 모델에서 발생하는 네트워크 지연 시간
- 대부분의 클라이언트 라이브러리에서 지원한다.
♬ Transaction
- 다수의 명령을 하나의 트랜잭션으로 처리되면서 원자성이 보장된다
- 중간에 에러가 발생하면 모든 작업이 rollback된다
- 하나의 트랜잭션이 처리되는 동안 다른 클라이언트의 요청이 중간에 끼어들수 없다
- 원자성(Automicity)
- All or Nothing : 모든 작업이 적용되거나 하나도 적용되지 않거나
- Pipeline은 네트워크 퍼포먼스 향상을 위해 여러개의 명령어를 한 번에 요청
- Transaction은 작업의 원자성을 보장하기 위해 다수의 명령을 하나처럼 처리하는 기술
- 두개는 다르고 동시에 사용도 가능하다
- 명령어
- MULTI : 트랜잭션의 시작
- DISCARD : rollback
- EXEC : 트랜잭션 적용
🎲 레디스 다양한 데이터 타입의 활용
♬ One-Time Password(임시 비밀번호[String])
- 인증을 위해 사용되는 임시 비밀번호
♬ Distributed Lock(분산락[String])
- 분산 환경의 다수의 프로세스에서 동일한 자원에 접근할 때 동시성 문제를 해결한다
- 해당 공유 자원을 표현하는 이름으로 Key를 설정하고 NX를 통해 key가 없다면 lock을 획득
- 이미 존재한다면 nil을 리턴한다
- lock을 획득한 자원이 해결되면 delete를 하고 다음 요청이 lock을 다시 진행한다
♬ Rate Limiter(비율 계산기[String])
- 시스템 안정성/보안을 위해 요청의 수를 제한하는 기술
- IP, USER, Application 등등을 기준으로 제한한다.
- Fixed-window Rate Limiting
- 고정된 시간(e.g. 1분)안에 요청 수를 제한하는 방법
- 10분에 서버에 요청을 하면 1.1.1.1:10 이라는 key를 만든다. 이뜻은 10분부터 11분까지의 요청한 횟수를 체크한다
- 만약 한계를 20으로 잡았다면 20이 넘어가면 429 오류를 발생시킨다. 하지만 그 전까진 정상적인 응답을 한다
- 최악의 경우
- 10분 59초에 20번의 요청이 오고 11분이 되면서 20개의 요청이 오면 2초안에 40개의 요청을 처리해야한다
♬ SNS Activity Feed(소셜 네트워크 활동 피드[List])
- 사용자 또는 시스템과 관련된 활동이나 업데이트를 시간순으로 정렬하여 보여주는 기능
- Fan-Out : 단일 데이터를 한 소스에서 여러 목적지로 동시에 전달하는 메시징 패턴
- user1 이 어떠한 게시물에 좋아요를 누르면 해당 이벤트는 피드를 관리하는 서비스로 전달되고
- 레디스는 이것에 흥미가 있을만한 사람들의 피드에 해당 이벤트를 전달한다.
- 이후 자신의 피드를 조회한 user2 는 0 ~ 9index 즉 10개의 피드 내용을 순서대로 보여주게 되면서 확인한다
♬ Shopping Cart(장바구니[Set])
- 사용자가 구매를 원하는 상품을 임시로 모아두는 가상의 공간
- 수시로 변경이 발생할 수 있고, 실제 구매로는 이어지지 않을 수 있다
- 상품을 추가하면 SADD 로 해당 SET데이터인 cart에 item이 담기고
- 이후에 조회를 할때는 SMEMBERS를 통해 조회하여 가져온다.
♬ Login Session(로그인[Hash])
- 사용자의 로그인 상태를 유지하기 위한 기술
- 로그인시 세션의 갯수를 제한하여, 동시에 로그인 가능한 디바이스 갯수를 제한한다 - 동시 로그인 제한
- 인증을 완료하면 유저의 정보를 SET의 이름을 담아 저장하고 set-cookie에 해당 SET의 이름을 담아 전달한다
- 이후엔 cookie에 데이터를 담아 전달한다. 그럼 저장된 SET을 확인하고 처리한다
♬ Sliding Window Rate Limiter(비율 계산기2[SortedSet])
- 시간에 따라 window를 이동시켜 동적으로 요청 수를 조절하는 기술
- Fixed Window : window의 시간마다 허용량이 초기화 된다
- Sliding Window : 시간이 경과함에 따라 window가 같이 움직인다
♬ Geofencing(반경 탐색[Geospatial])
- 위치를 활용하여 지도 상의 가상의 경계 또는 지리적 영역을 정의하는 기술
- 만약 내가 있는 범위내로 특정 가게만 찾고자 한다는 요청이 있다면
- 명령어를 이렇게 작성하면 나온다.
♬ Online Status(온라인 상태 표시[Bitmap])
- 사용자의 현재 상태를 표시하는 기능
- 실시간성을 완벽히 보장하지 않는다. 수시로 변경되는 값이기 때문이다.
♬ Visitors Count(방문자 수 계산[HyperLogLog])
- 방문자 수를 대략적으로 추정하는 경우 정확한 횟수를 셀 필요 없이 대략적인 어림치만 알고자 하는 경우
♬ Unique Events(중복 이벤트 제거[BloomFilter])
- 동일한 요청이 중복으로 처리되지 않게 하기 위해 빠르게 해당 Item이 중복인지 확인한다.
'CS' 카테고리의 다른 글
프레임 워크와 라이브러리의 차이 (0) | 2024.05.22 |
---|---|
💻 멀티 프로세스와 멀티 스레드 (0) | 2023.10.16 |
DNS(Domain Name System) (0) | 2023.05.03 |
HTTP(3). 성능향상 (0) | 2023.05.01 |
Cookie와 Session (4) | 2023.05.01 |