Redis 에서 키 의 만 료 삭제 정책 에 대해 자세히 설명 합 니 다.
이 문 제 는 세 가지 가능 한 답 이 있 는데 각각 세 가지 다른 삭제 전략 을 대표 한다.
4.567917.정시 삭제:키 의 만 료 시간 을 설정 하 는 동시에 타이머(timer)를 만 듭 니 다.타이머 가 키 의 만 료 시간 이 다가 오 면 바로 키 에 대한 삭제 작업 을 수행 합 니 다4.567917.타성 삭제:방치 키 가 만 료 되 더 라 도 키 공간 에서 키 를 가 져 올 때마다 얻 은 키 가 만 료 되 었 는 지 확인 하고 만 료 되면 이 키 를 삭제 합 니 다.기한 이 지나 지 않 았 다 면 이 키 를 되 돌려 줍 니 다4.567917.정기 적 으로 삭제:일정 시간 마다 프로그램 은 데이터 베 이 스 를 검사 하고 기한 이 지난 키 를 삭제 합 니 다.만 료 키 를 얼마나 삭제 하고 데이터 베 이 스 를 얼마나 검사 해 야 하 는 지 는 알고리즘 에 의 해 결정 된다이 세 가지 정책 중에서 첫 번 째 와 세 번 째 는 주동 적 으로 정책 을 삭제 하고 두 번 째 는 수 동적 으로 정책 을 삭제 합 니 다.
머리말
Redis 를 사용 할 때 저 희 는 EXPIRE 나 EXPIREAT 명령 을 사용 하여 key 에 게 만 료 된 삭제 시간 을 설정 할 수 있 습 니 다.구조 체 redisDb 의 expires 사전 은 모든 key 의 만 료 시간 을 저장 합 니 다.이 사전(dict)의 key 는 지침 으로 redis 의 한 key 대상 을 가리 키 며 만 료 된 사전 의 value 는 만 료 시간 을 저장 하 는 정수 입 니 다.
/* Redis database representation. There are multiple databases identified
* by integers from 0 (the default database) up to the max configured
* database. The database number is the 'id' field in the structure. */
typedef struct redisDb {
dict *dict; /* The keyspace for this DB */
dict *expires; /* */
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP) */
dict *ready_keys; /* Blocked keys that received a PUSH */
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */
int id; /* Database ID */
long long avg_ttl; /* Average TTL, just for stats */
} redisDb;
만 료 시간 설정EXPIRE,EXPIREAT 든 PEXPIRE 든 PEXPIREAT 든 저층 의 구체 적 인 실현 은 같다.Redis 의 key 공간 에서 만 료 시간 을 설정 할 이 key 를 찾 은 다음 이 entry(key 의 포인터,만 료 시간)를 만 료 사전 에 추가 합 니 다.
void setExpire(redisDb *db, robj *key, long long when) {
dictEntry *kde, *de;
/* Reuse the sds from the main dict in the expire dict */
kde = dictFind(db->dict,key->ptr);
redisAssertWithInfo(NULL,key,kde != NULL);
de = dictReplaceRaw(db->expires,dictGetKey(kde));
dictSetSignedIntegerVal(de,when);
}
만 료 삭제 정책
키 가 만 료 되면 언제 삭 제 됩 니까?Redis 에는 두 가지 만 료 삭제 정책 이 있 습 니 다.(1)타성 만 료 삭제;(2)정기 삭제.다음은 구체 적 으로 보 자.
타성 만 료 삭제
Redis 는 읽 기와 쓰기 명령 을 실행 할 때 이 키 를 먼저 찾 습 니 다.타성 삭 제 는 키 를 찾기 전에 키 가 만 료 되면 이 키 를 삭제 합 니 다.
robj *lookupKeyRead(redisDb *db, robj *key) {
robj *val;
expireIfNeeded(db,key); //
val = lookupKey(db,key);
if (val == NULL)
server.stat_keyspace_misses++;
else
server.stat_keyspace_hits++;
return val;
}
정기 삭제key 의 정기 삭 제 는 Redis 의 주기 적 인 작업(server Cron,기본 100 ms 마다 실행)에서 진행 되 며,Redis 가 발생 하 는 master 노드 입 니 다.slave 노드 는 주 노드 의 DEL 명령 을 통 해 key 를 삭제 하 는 목적 을 달성 하기 때 문 입 니 다.
각각 db(기본 설정 수 는 16)를 차례로 옮 겨 다 니 며,각각 db 에 대해 순환 할 때마다 무 작위 로 20 개(ACTIVEEXPIRE_CYCLE_LOOKUPS_PER_LOOP)key 는 만 료 여 부 를 판단 하고,1 라운드 에서 선택 한 key 가 25%보다 적 으 면 반복 을 종료 하 며,그 외 교체 과정 에서 일정 시간 제한 을 초과 하면 만 료 삭제 과정 을 종료 한다.
for (j = 0; j < dbs_per_call; j++) {
int expired;
redisDb *db = server.db+(current_db % server.dbnum);
/* Increment the DB now so we are sure if we run out of time
* in the current DB we'll restart from the next. This allows to
* distribute the time evenly across DBs. */
current_db++;
/* Continue to expire if at the end of the cycle more than 25%
* of the keys were expired. */
do {
unsigned long num, slots;
long long now, ttl_sum;
int ttl_samples;
/* db key, db*/
if ((num = dictSize(db->expires)) == 0) {
db->avg_ttl = 0;
break;
}
slots = dictSlots(db->expires);
now = mstime();
/* When there are less than 1% filled slots getting random
* keys is expensive, so stop here waiting for better times...
* The dictionary will be resized asap. */
if (num && slots > DICT_HT_INITIAL_SIZE &&
(num*100/slots < 1)) break;
/* The main collection cycle. Sample random keys among keys
* with an expire set, checking for expired ones. */
expired = 0;
ttl_sum = 0;
ttl_samples = 0;
if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)
num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;// 20
while (num--) {
dictEntry *de;
long long ttl;
if ((de = dictGetRandomKey(db->expires)) == NULL) break;
ttl = dictGetSignedIntegerVal(de)-now;
if (activeExpireCycleTryExpire(db,de,now)) expired++;
if (ttl > 0) {
/* We want the average TTL of keys yet not expired. */
ttl_sum += ttl;
ttl_samples++;
}
}
/* Update the average TTL stats for this database. */
if (ttl_samples) {
long long avg_ttl = ttl_sum/ttl_samples;
/* Do a simple running average with a few samples.
* We just use the current estimate with a weight of 2%
* and the previous estimate with a weight of 98%. */
if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;
db->avg_ttl = (db->avg_ttl/50)*49 + (avg_ttl/50);
}
/* 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. */
iteration++;
if ((iteration & 0xf) == 0) { /* 16 */
long long elapsed = ustime()-start;
latencyAddSampleIfNeeded("expire-cycle",elapsed/1000);
if (elapsed > timelimit) timelimit_exit = 1;
}
//
if (timelimit_exit) return;
/* db , 25% key , key */
} while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);
}
총결산타성 삭제:읽 기와 쓰기 전에 key 가 만 료 되 었 는 지 판단 합 니 다.
정기 삭제:정기 표본 추출 키,만 료 여부 판단
자,이상 이 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redis 해시에 대한 완벽한 가이드변경 가능하므로 필요에 따라 쉽게 변경하고 업데이트할 수 있습니다. Redis 해시는 구조가 평평하므로 JSON에서와 같이 여러 수준을 가질 수 없습니다. redis 해시의 명명 규칙은 hash:key 로 입력되므로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.