면접 회고를 목적으로 몰랐던 개념을(모르고리즘 시리즈와는 별개로) 망했어요 시리즈로 한 번 정리해보도록 하지
(하기 내용은 우아한 테크 세미나 강의를 보고 따라 정리함)
[우아한테크세미나] 191121 우아한레디스 by 강대명님
Cache를 왜 쓰나?
Factorial
접근 속도가 다를 때
어디서 많이 사용하나?
파레토 법칙
Cashe 구조
왜 Collection이 중요한가?
현재 유저 123의 친구 key는 friends : 123, 현재 친구 A가 있는 중
GOOD
시간순서 | T1(친구 B 추가) | T2(친구 C 추가) | 최종상태 |
---|---|---|---|
1 | friends:123 읽기 | A | |
2 | 친구 B 추가 | A | |
3 | friends:123 쓰기 | A, B | |
4 | friends:123 읽기 | A, B | |
5 | 친구 C 추가 | A, B | |
6 | friends:123 쓰기 | A, B, C |
HOW?
시간순서 | T1(친구 B 추가) | T2(친구 C 추가) | 최종상태 |
---|---|---|---|
1 | friends:123 읽기 | A | |
2 | friends:123 읽기 | A | |
3 | 친구 B 추가 | A | |
4 | 친구 C 추가 | A | |
5 | friends:123 쓰기 | A, B | |
6 | friends:123 쓰기 | A, C |
HOW?
시간순서 | T1(친구 B 추가) | T2(친구 C 추가) | 최종상태 |
---|---|---|---|
1 | friends:123 읽기 | A | |
2 | friends:123 읽기 | A | |
3 | 친구 B 추가 | A | |
4 | 친구 C 추가 | A | |
5 | friends:123 쓰기 | A, C | |
6 | friends:123 쓰기 | A, B |
Context Switching 때문에 T1, T2가 어떻게 일어날지 모름
Redis는 어디서 사용하는가?
Redis Collections
자료 구조 선택이 중요한 이유 : Big O
→ 서비스 속도!
→ O(1), O(n)
Strings (key/value) : 단일 key, 멀티 key
Set token:1234567 askdljfkl;asjdfl
Get token:1234567
Mset token:1234567 asdjkfjask;djf email:1234567 lilo@gmail.com
Mget goken:1234567 email:1234567
insert into users(name, email) values(’lilo’, ‘lilo@gmail.com’);
Set name:lilo lilo
Set email:lilo lilo@gmail.com
Mset name:lilo lilo email:lilo lilo@gmail.com
List (앞이나 뒤에 데이터를 넣는 것은 빠르지만 중간에 삽입하는 경우는 list를 쓰면 안된다)
Lpush <key> <A>
Rpush <key> <B>
Lpush <key> <C>
Rpush <key> <D, A>
key : (C, A, B, D, A)
LPOP <key>
RPOP <key>
RPOP <key>
Set (중복된 데이터를 넣지 않을 때, 찾는 건 빠름)
<Key> <Value>
<key>
<key> <value>
Sorted Set (순서를 보장함, score 순으로 정렬 가능)
<Key> <Score> <Value>
<Key> <StartIndex> <EndIndex>
select * from rank order by score limit 50, 20;
→ zrange rank 50 70
select * from rank order by score desc limit 50, 20;
→ zrevrange rank 50 70
select * from rank where score >= 70 and score <100;
→ zrangebyscore rank 70 100` select * from rank where score > 70;
→ zrangebyscore rank (70+inf
Hash
Key 밑에 sub key가 존재
Hmset <key> <subkey1> <value1> <subkey2> <value2>
Hgetall <key>
Hget <key> <subkey>
Hmget <key> <subkey1> <subkey2> ........ <subkeyN>
Insert into users(name, email) values('lilo', 'lilo@gmail.com');
→ hmset lilo name lilo email lilo@gmail.com
COLLECTION 주의 사항
메모리 관리를 잘하자
Redis가 메모리를 많이 쓰면 open the hellgate
Redis는 In-Memory Data Store
Physical Memory 이상을 사용하면 문제가 발생
Maxmemory를 설정하더라도 이보다 더 사용할 가능성이 큼 → 메모리 관리 필요
메모리 allocator에 의존해서 사용하는데, memory allocator의 구현에 따라서 성능이 왔다갔다 함
memory allocator가 지웠다고 하지만 memory를 가지고 있을 때도 있음
Redis가 자기가 사용하는 memory를 잘 모름(메모리 파편화)
→ jemlloc에 힌트를 주는 기능이 있으나, 버전에 따라서 다르게 동작 할 수 있음
많은 업체가 현제 메모리를 사용해서 Swap을 쓰고 있다는 것을 모를때가 많음
큰 메모리를 사용하는 instance 하나 보다는 적은 메모리를 사용하는 instance 여러 개가 안전함
→ fork를 할 때 read만 많으면 상관없는데 write가 heavy한 Redis는 메모리를 복사 할 때(copy on wright) 최대 두 배까지 쓸 수 있음
메모리가 부족할 떄는?
zlbytes | zltail | zllen | entry | ... | entry | zlend |
---|
O(N) 관련 명령어는 주의하자
Redis는 싱글 뜨레드
만약에 하나가 1초 걸린다 → 99999개 명령은 1초 기다림
→ timeout * 99999개 → 서비스 폭발 → 망한다!!!
TCP에서 패킷이 끊어져서 들어오는데 processInputBuffer라는 곳에서 패킷을 하나의 command로 만들어서 커맨드가 완성됐는지 확인 → processCommand & reset이라는 것을 타고 들어오는데 그 때 완성된 커맨드 하나를 실행시키는 구조 → 처리되는 동안 뒤에 패킷은 쌓이고 있음 → 이 하나가 loop를 탈출해야 다른 명령 처리 가능
Redis Replication
redis.conf 권장설정 Tip
데이터의 특성에 따라서 선택할 수 있는 방법이 달라진다
Application
modular server(id 값 % 서버갯수(n)의 값이 modular 번호)
서버가 꽉 찾음 → 서버 증설해야 함 → 서버 추가할 때마다 기존 데이터 움직임 → rebalancing 됨
서버가 죽었을 때/장애가 생겼을 때 → 또 rebalancing 생김
→ 장비가 늘어나거나 줄었을 때 발생할 수 있는 문제
Consistent Hashing
key 값을 해싱해서 나보다 크면서 가장 가까운 서버로 이동
(큰값이 없으면 가장 첫번째로)
예) 15000이 나오면 10000, 20000, 30000 서버 중에 20000으로 간다
→ 20000 서버가 죽었을 때 17500만 30000으로 이동하고 다른 데이터들은 그대로
→ 서버가 죽거나 증설했을 때 해당 서버의 데이터만 이동하면 됨
→ 1/n만큼만 움직인다 키의 해쉬 값이 해쉬가 일정하면 값이 일정하기 때문에 가능
twemproxy를 사용하는 방법
Sharding
데이터를 어떻게 나눌 것인가?
데이터를 어떻게 찾을 것인가?
하나의 데이터를 모든 서버에서 찾아야 한다면?
Range
그냥 특성 range를 정의하고 해당 range에 속하면 거기에 저장
1-10000 | 10001-200000 | 20001-30000 |
---|---|---|
id = 5001 | id = 15400 | id = 23000 |
id = 1000 | id = 11002 | |
id = 13003 |
이벤트를 해서 2번에 몰렸다가 다 탈퇴 → 2번 서버가 놈 → 다른 데이터가 2번으로 이동을 못함
→ 서버의 상황에 따라 놀고 있는 서버와 안놀고 있는 서버와 극심하게 나눠질 수 있음
→ 확장은 편하지만 중간에 빠져나가거나 초창기 유저가 저장 되어 있는 서버만 계속 일함
Indexed server
modular
Redis Cluster