Redis는 무엇이고 어떻게 사용할까?
Redis란
key:value
구조의 저장소- In-memory 데이터 구조 저장소
- 지원하는 데이터 구조
- Strings, set, sorted-set, hashes, list
- Hyperloglog, bitmap, geospatial index
- Strea m
- Only 1 Committer
- Redis 소스 코드를 고칠 수 있는 권한이 있는 사람은 딱 한 명!
Cache
Redis는 캐싱에 많이 사용되므로 알아두면 도움이 된다.
Cache의 정의
- Cache는 나중에 요청올 결과를 미리 저장해두었다가 빠르게 서비스 해주는 것을 의미
- ex) DP, 10! = 10 * 9!= 10 * 9 * 8! = 10 * 9 * 8 * 7! (팩토리얼 숫자가 크다면 미리 캐싱해두면 연산이 훨씬 빨라짐)
- 파레토 법칙
- 20:80 법칙으로, 우리 사회에서 일어나는 현상의 80%는 20%의 원인으로 인하여 발생
- 즉, 전체 트래픽의 80%는 20%의 특정 데이터 요청
웹 서버에서 사용되는 Cache 구조
- 캐싱을 적용하지 않은 구조로, DB안에 모든 데이터가 존재하는 구조
- 디스크에 데이터를 저장하는 일반적인 구조
Look aside Cache
- Web Server는 데이터가 존재하는지 Cache를 연계 확인
- Cache에 데이터가 있으면 Cache에서 가져온다.
- Cache에 데이터가 없으면 DB에서 데이터를 가져와 Cache에 저장하고 값을 가져온다.
Write Back
- Web Server는 모든 데이터를 Cache에만 저장
- Cache에 특정 시간동안의 데이터가 저장된다.
- 그리고 배치처리를 통해 Cache에 있는 데이터를 DB에 저장한다.
- DB에 저장되었다면 Cache에는 해당 데이터를 삭제한다.
- 이 방식의 단점
- 서버 장애가 생기면 데이터가 날아갈 수도 있다.
- Cache에 업데이트 하고 메모리에는 바로 업데이트를 하지 않기 때문에, Cache와 메모리가 서로 값이 다른 경우가 발생할 수 있다.
- 그래서 데이터 손실 위험을 줄이기 위해 로그를 Redis에 넣어두고 배치적으로 데이터를 저장할 때 많이 사용된다.
insert 쿼리를 한번씩 500번 날리는 것과 insert 쿼리 한번에 500개를 붙여서 날리는 것중 어느 것이 더 빠를까?
후자가 훨씬 빠르다. Write Back 방식은 이와 같은 원리를 활용하여 데이터가 일시적으로 캐시에만 저장되고, 이후 배치 작업을 통해 DB에 한꺼번에 기록한다.
왜 Collection이 중요한가?
Redis의 장점과 Memcached보다 Redis가 왜 좋은지 이해하는데 도움이 된다.
Collection을 잘 사용함으로써 여러가지 개발 시간을 단축시키고, 문제를 줄여줄 수 있다.
개발의 편의성
랭킹 서버를 직접 구현한다고 생각해보자.
- 가장 간단한 방법
- DB에 유저의 Score를 저장하고 Score로 order by 정렬 후 읽어오기
- 하지만 데이터가 많아지면 속도에 문제가 발생하게 된다. 결국에는 디스크를 사용하기 때문이다.
- In-memory 기준으로 랭킹 서버의 구현이 필요
- Redis의 Sorted Set을 이용하면, 랭킹을 구현 할 수 있음
- 다만 가져다 쓰면 한계에 종속적일 수 있다.
개발의 난이도
친구 리스트를 KEY/VALUE 형태로 저장한다고 생각해보자.
- 현재 유저123의 친구 Key는 friends:123, 현재 친구 A가 있는 중이고 예를 들어 [“A”]와 같이 현재 친구 A가 포함되어 있다.
- 친구 B와 C를 추가한다고 가정한다면
- Transaction 1 (B 추가), Transaction 2 (C 추가)가 서로 동일한 시간에 실행되면 B나 C중 하나는 추가가 안 될 수도 있다.(Race Condition)
- 그렇다면 Redis는?
- Redis의 경우는 자료구조가 Atomic하기 때문에, 해당 Race Condition을 피할 수 있다.
Redis는 언제 사용될까?
- Remote Data Store
- 여러 서버에서 데이터를 공유하고 싶을 때
- 메모리 기반의 데이터 저장소로 빠른 응답 속도 제공, 싱글 쓰레드이기 때문에 원자성 보장
- 서버 한 대에서만 필요하면, 전역 변수를 쓰면 되지 않을까?
- Redis는 싱글 쓰레드로 동작하여 원자성을 보장하기 때문에
- 주로 많이 쓰는 곳들
- 인증 토큰 등을 저장
- 랭킹 보드로 사용(Sorted Set)
- 유저 API Limit
- 잡큐(list)
Redis Collections
Redis가 지원하는 다양한 자료구조와 선택하는 기준에 대해서 다룬다.
Strings
- 기본적인
key:value
형태 - 사용법
- 삽입
- Single:
Set <key> <value>
(ex.SET token:1234567 "abcdefdkfdakd"
) - Multi:
mset <key1> <value1> <key2> <value2> ... <keyN> <valueN>
(ex.mset token abcd email mistyblue@gmail.com
)
- Single:
- 조회
- Single:
Get <key>
(ex.GET token:1234567
) - Multi:
mget <key1> <key2> ... <keyN>
(ex.mget token email
)
- Single:
- 삽입
List
- 일반적인 List와 동일
- 앞과 뒤에서 넣는 것은 빠르지만 중간에 삽입이 느리다.
- 사용법
- insert
Lpush <key> <A>
->Key:(A)
Rpush <key> <B>
->Key:(A, B)
Lpush <key> <C>
->Key:(C, A, B)
Rpush <key> <D, A>
->Key:(C, A, B, D, A)
- pop
Key:(C, A, B, D, A)
LPOP <key>
->Pop C, Key:(A, B, D, A)
RPOP <key>
->Pop A, Key:(A, B, D)
- lpop, blpop, rpop, brpop
Key: ()
LPOP <key>
->No data
BLPOP <key>
-> 누가 데이터를 Push하기 전까지 대기
- String과 동일하게 key를 통해 카테고리를 만들 수 있다.
- insert
Set
- 중복된 값을 넣지 않는 자료구조
- 데이터가 있는지 없는지 체크하는 용도로 사용한다.
- 사용법
SADD <key> <value>
-> Value가 이미 Key에 있으면 추가되지 않는다.SMEMBERS <key>
-> 모든 Value를 반환.SISMEMBER <key> <value>
-> value가 존재하면 1, 없으면 0
- 예시
- 특정 유저를 Follow하는 목록을 저장할 때 많이 사용된다. (unique한 특징이 있을 때)
Sorted Sets
- Set은 순서가 없지만, Sorted Set은 순서를 보장한다.
- 사용법
ZADD <key> <score> <value>
-> Value가 이미 key에 있으면 해당 Score로 변경된다.ZRANGE <key> <startIdx> <endIdx>
-> 해당 Index 범위 값을 모두 돌려준다. (모든 범위는Zrange testkey 0 -1
)
- 특징
- 유저 랭킹 보드로 사용할 수 있음.
- Set의 숫자는 double 타입이기 때문에 값이 정확하지 않을 수 있다.
SQL을 대체한다면?
- SQL:
select * from rank order by score limit 50, 20;
- Redis:
Zrange rank 50 70
- Redis:
- SQL:
select * from rank order by score desc limit 50, 20;
- Redis:
Zrevrange rank 50 70
- Redis:
Hash
key:value
안에 다시key:value
를 가질 수 있게 한다.- 사용법
Hmset <key> <subkey1> <value1> <subkey2> <value2>
Hgetall <key>
-> 해당 key의 모든 subkey와 value를 가져온다.Hget <key> <subkey>
Hmget <key> <subkey1> <subkey2> ... <subkeyN>
SQL을 대체한다면?
- SQL:
insert into Users(name, email) values ('juseon', 'mistyblue0302@gmail.com')
- Redis:
Hmset juseon name juseon email mistyblue0302@gmail.com
- Redis:
Collection 주의 사항
- 하나의 컬렉션에 너무 많은 아이템을 담으면 좋지 않음
- 10000개 이하 몇천개 수준으로 유지하는게 좋음.
- Expire는 Collection의 item 개별로 걸리지 않고 전체 Collection에 대해서만 걸림.
- 즉 10000개의 아이템을 가진 해당 Collection에 expire가 걸려있다면 그 시간 후에 10000개의 아이템이 모두 삭제될 수도 있다.
참고