개요
레디스는 키에 Time To Live (TTL) 이 지정된 경우 키가 만료(expired) 되면 해당 키를 제거한다.
어떤 방식으로 만료된 키를 제거하는 것일까?
레디스는 2가지 방법을 제공한다.
바로 Passive 방식과 Active 방식이다.
Passive way
클라이언트가 만료된 키에 접근하면, 그때야 비로소 해당 키를 제거한다.
장점
CPU 오베헤드가 발생하지 않는다.
단점
만료된 키에 클라이언트가 접근하지 않는다면?
=> 만료된 키가 제거되지 않는다.
=> 메모리 낭비 발생
Active way
아래 과정을 1초에 대략 10회 진행한다.
- TTL 값이 있는 키 20개를 랜덤하게 뽑는다.
- 뽑은 키 중 만료된 키만 제거한다.
- (2.)에서 25% 이상 키가 제거되었다면 (1.)로 돌아간다.
- (2.)에서 25% 미만 키가 제거되었다면 (2.)로 돌아간다.
둘중 어느 방법이 쓰이나요?
기본적으로 둘 다 쓰인다.
Active 방식으로 TTL을 검사하며 지우고,
이와 별개로 Client 가 접근한 키가 만료된 경우 Passive 방식으로 지운다.
Active 방식이 쓰인다고요? 레디스는 싱글 스레드인데요?
맞다.
메인 이벤트 루프 싱글 스레드 하나 내에서 Active expiration 과 클라이언트 command 를 모두 처리한다.
대신, Non-Blocking 방식으로 동작하며 CPU 점유 시간을 제한한다.
active 방식 함수의 일부 코드를 발췌했다.
void activeExpireCycle(int type) {
// iteration 간 CPU 점유시간을 제한하기 위한 파라미터
config_cycle_slow_time_perc = ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC +
2*effort,
// .. 중략
/* We can use at max 'config_cycle_slow_time_perc' percentage of CPU
* time per iteration. Since this function gets called with a frequency of
* server.hz times per second, the following is the max amount of
* microseconds we can spend in this function. */
timelimit = config_cycle_slow_time_perc*1000000/server.hz/100;
timelimit_exit = 0;
if (timelimit <= 0) timelimit = 1;
if (type == ACTIVE_EXPIRE_CYCLE_FAST)
timelimit = config_cycle_fast_duration; /* in microseconds. */
// .. 중략
/* We can't block forever here even if there are many keys to
* expire. So after a given amount of milliseconds return to the
* caller waiting for the other active expire cycle. */
if ((iteration & 0xf) == 0) { /* check once every 16 iterations. */
elapsed = ustime()-start;
if (elapsed > timelimit) {
timelimit_exit = 1;
server.stat_expired_time_cap_reached_count++;
break;
}
}
}
active 방식에서 CPU 를 점유하는 시간을 제한(config_cycle_slow_time_perc, timelimit) 하고있다.
'DataBase > Redis' 카테고리의 다른 글
[Redis] TTL - 언제 업데이트 될까? (0) | 2024.12.22 |
---|---|
[Redis] DataStructure Lifecycle (0) | 2024.12.19 |
[Redis] redis.conf 권장설정 (0) | 2021.12.21 |