찾다
데이터 베이스RedisRedis 데이터 제거 전략에 대한 자세한 설명

Redis 데이터 제거 전략에 대한 자세한 설명

이 기사에서 말하는 내용은 redis가 최대 메모리를 설정한 후 캐시에 설정된 데이터의 크기가 일정 비율을 초과한다는 것입니다. 구현된 제거 전략은 만료된 키를 삭제하는 전략이 아닙니다. 매우 비슷합니다. (권장: redis 비디오 튜토리얼)

redis에서는 redis.conf에서 maxmemory 값을 구성하여 사용자가 최대 메모리 크기를 설정하고 메모리 제거 기능을 활성화할 수 있는데, 이는 메모리가 제한되어 있을 때 매우 유용합니다.

최대 메모리 크기를 설정하면 redis가 외부 세계에 안정적인 서비스를 제공할 수 있습니다.

Redis 메모리 데이터 세트의 크기가 특정 크기로 증가하면 데이터 제거 전략이 구현됩니다. Redis는 maxmemory-policy 설정 전략을 통해 6가지 데이터 제거 전략을 제공합니다.

휘발성-lru: 제거할 만료 시간이 설정된 데이터 세트(server.db[i].expires)에서 가장 최근에 사용된 데이터를 선택합니다.

휘발성- ttl : 만료 시간이 설정된 데이터 세트(server.db[i].expires)에서 만료될 데이터를 선택하여 제거합니다.

휘발성-random: 만료 시간이 설정된 데이터 세트(server.db[ i].expires) )

allkeys-lru: 데이터 세트(server.db[i].dict)에서 가장 최근에 사용된 데이터를 선택하여 제거합니다.

allkeys-random: 데이터 세트(server.db[i)에서 ].dict). dict) 모든 데이터 제거

no-enviction(eviction): 데이터 제거가 금지됩니다.

redis가 키-값 쌍을 제거하기로 결정한 후 데이터를 삭제하고 데이터 변경 메시지를 게시합니다. 로컬(AOF 지속성) 및 슬레이브(마스터-슬레이브 연결)

LRU 데이터 제거 메커니즘

서버 구성에 lru 카운터 server.lrulock을 저장하며 정기적으로 업데이트됩니다(redis 타이머 프로그램 serverCorn()) . server.lrulock의 값은 unixtime을 기준으로 계산됩니다.

또한 struct redisObject에서 각 redis 객체가 해당 lru를 설정한다는 것을 알 수 있습니다. 데이터에 액세스할 때마다 redisObject.lru가 업데이트되는 것이 가능합니다.

LRU 데이터 제거 메커니즘은 다음과 같습니다. 데이터 세트에서 여러 키-값 쌍을 무작위로 선택하고 그중 LRU가 가장 큰 키-값 쌍을 제거합니다. 따라서 Redis는 모든 데이터 세트에서 가장 최근에 사용된(LRU) 키-값 쌍을 얻는 것을 보장하지 않고 무작위로 선택된 몇 개의 키-값 쌍만 얻음을 보장합니다.

// redisServer 保存了 lru 计数器
struct redisServer {
...
unsigned lruclock:22; /* Clock incrementing every minute, for LRU */
...
};
// 每一个 redis 对象都保存了 lru
#define REDIS_LRU_CLOCK_MAX ((1<<21)-1) /* Max value of obj->lru */
#define REDIS_LRU_CLOCK_RESOLUTION 10 /* LRU clock resolution in seconds */
typedef struct redisObject {
// 刚刚好 32 bits
// 对象的类型,字符串/列表/集合/哈希表
unsigned type:4;
// 未使用的两个位
unsigned notused:2; /* Not used */
// 编码的方式,redis 为了节省空间,提供多种方式来保存一个数据
// 譬如:“123456789” 会被存储为整数 123456789
unsigned encoding:4;
unsigned lru:22; /* lru time (relative to server.lruclock) */
// 引用数
int refcount;
// 数据指针
void *ptr;

} robj;
// redis 定时执行程序。联想:linux cron
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
......
/* We have just 22 bits per object for LRU information.
* So we use an (eventually wrapping) LRU clock with 10 seconds resolution.
* 2^22 bits with 10 seconds resolution is more or less 1.5 years.
*
* Note that even if this will wrap after 1.5 years it&#39;s not a problem,
* everything will still work but just some object will appear younger
* to Redis. But for this to happen a given object should never be touched
* for 1.5 years.
*
* Note that you can change the resolution altering the
* REDIS_LRU_CLOCK_RESOLUTION define.

*/
updateLRUClock();
......
}
// 更新服务器的 lru 计数器
void updateLRUClock(void) {
server.lruclock = (server.unixtime/REDIS_LRU_CLOCK_RESOLUTION) &
REDIS_LRU_CLOCK_MAX;
}

TTL 데이터 제거 메커니즘

redis 데이터 세트 데이터 구조는 키-값 쌍 만료 시간 테이블, 즉 redisDb.expires를 저장합니다. LRU 데이터 제거 메커니즘과 유사하게 TTL 데이터 제거 메커니즘은 다음과 같습니다. 만료 시간 테이블에서 여러 키-값 쌍을 무작위로 선택하고 TTL이 가장 큰 키-값 쌍을 꺼내 제거합니다.

마찬가지로 Redis는 모든 만료 시간 테이블에서 가장 빠르게 만료되는 키-값 쌍을 획득한다고 보장하지 않고 무작위로 선택된 소수의 키-값 쌍만 획득한다는 것을 알 수 있습니다.

Summary

redis는 서비스 클라이언트에서 명령을 실행할 때 사용된 메모리가 과도한지 여부를 감지합니다. 한도를 초과하면 데이터가 삭제됩니다.

// 执行命令
int processCommand(redisClient *c) {
......
// 内存超额
/* Handle the maxmemory directive.
*
* First we try to free some memory if possible (if there are volatile
* keys in the dataset). If there are not the only thing we can do
* is returning an error. */
if (server.maxmemory) {
int retval = freeMemoryIfNeeded();
if ((c->cmd->flags & REDIS_CMD_DENYOOM) && retval == REDIS_ERR) {
flagTransaction(c);
addReply(c, shared.oomerr);
return REDIS_OK;
}
}
......
}
// 如果需要,是否一些内存
int freeMemoryIfNeeded(void) {
size_t mem_used, mem_tofree, mem_freed;
int slaves = listLength(server.slaves);
// redis 从机回复空间和 AOF 内存大小不计算入 redis 内存大小
/* Remove the size of slaves output buffers and AOF buffer from the
* count of used memory. */
mem_used = zmalloc_used_memory();
// 从机回复空间大小
if (slaves) {
listIter li;
listNode *ln;
listRewind(server.slaves,&li);
while((ln = listNext(&li))) {
redisClient *slave = listNodeValue(ln);
unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);
if (obuf_bytes > mem_used)
mem_used = 0;
else
mem_used -= obuf_bytes;
}
}
// server.aof_buf && server.aof_rewrite_buf_blocks
if (server.aof_state != REDIS_AOF_OFF) {
mem_used -= sdslen(server.aof_buf);
mem_used -= aofRewriteBufferSize();
}
// 内存是否超过设置大小
/* Check if we are over the memory limit. */
if (mem_used <= server.maxmemory) return REDIS_OK;
// redis 中可以设置内存超额策略
if (server.maxmemory_policy == REDIS_MAXMEMORY_NO_EVICTION)
return REDIS_ERR; /* We need to free memory, but policy forbids. */
/* Compute how much memory we need to free. */
mem_tofree = mem_used - server.maxmemory;
mem_freed = 0;
while (mem_freed < mem_tofree) {
int j, k, keys_freed = 0;
// 遍历所有数据集
for (j = 0; j < server.dbnum; j++) {
long bestval = 0; /* just to prevent warning */
sds bestkey = NULL;
struct dictEntry *de;
redisDb *db = server.db+j;
dict *dict;
// 不同的策略,选择的数据集不一样
if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||
server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM
{
dict = server.db[j].dict;
} else {
dict = server.db[j].expires;
}
// 数据集为空,继续下一个数据集
if (dictSize(dict) == 0) continue;
// 随机淘汰随机策略:随机挑选
/* volatile-random and allkeys-random policy */
if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM ||
server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_RANDOM)
{
de = dictGetRandomKey(dict);
bestkey = dictGetKey(de);
}
// LRU 策略:挑选最近最少使用的数据
/* volatile-lru and allkeys-lru policy */
else if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||
server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)
{
// server.maxmemory_samples 为随机挑选键值对次数
// 随机挑选 server.maxmemory_samples个键值对,驱逐最近最少使用的数据
for (k = 0; k < server.maxmemory_samples; k++) {
sds thiskey;
long thisval;
robj *o;
// 随机挑选键值对
de = dictGetRandomKey(dict); 
// 获取键
thiskey = dictGetKey(de); 
/* When policy is volatile-lru we need an additional lookup
* to locate the real key, as dict is set to db->expires. */
if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)
de = dictFind(db->dict, thiskey);
o = dictGetVal(de); 
// 计算数据的空闲时间
thisval = estimateObjectIdleTime(o);
// 当前键值空闲时间更长,则记录
/* Higher idle time is better candidate for deletion */
if (bestkey == NULL || thisval > bestval) {
bestkey = thiskey;
bestval = thisval;
}
}
} 
// TTL 策略:挑选将要过期的数据
/* volatile-ttl */
else if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_TTL) {
// server.maxmemory_samples 为随机挑选键值对次数
// 随机挑选 server.maxmemory_samples个键值对,驱逐最快要过期的数据
for (k = 0; k < server.maxmemory_samples; k++) {
sds thiskey;
long thisval;
de = dictGetRandomKey(dict);
thiskey = dictGetKey(de);
thisval = (long) dictGetVal(de);
/* Expire sooner (minor expire unix timestamp) is better
* candidate for deletion */
if (bestkey == NULL || thisval < bestval) {
bestkey = thiskey;
bestval = thisval;
}
}
}
// 删除选定的键值对
/* Finally remove the selected key. */
if (bestkey) {
long long delta;
robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
// 发布数据更新消息,主要是 AOF 持久化和从机
propagateExpire(db,keyobj);
// 注意, propagateExpire() 可能会导致内存的分配, propagateExpire()
提前执行就是因为 redis 只计算 dbDelete() 释放的内存大小。倘若同时计算 dbDelete() 释放的内存
和 propagateExpire() 分配空间的大小,与此同时假设分配空间大于释放空间,就有可能永远退不出这个循环。
// 下面的代码会同时计算 dbDelete() 释放的内存和 propagateExpire() 分配空间的大小:
// propagateExpire(db,keyobj);
// delta = (long long) zmalloc_used_memory();
// dbDelete(db,keyobj);
// delta -= (long long) zmalloc_used_memory();
// mem_freed += delta;
/////////////////////////////////////////
/* We compute the amount of memory freed by dbDelete() alone.
* It is possible that actually the memory needed to propagate
* the DEL in AOF and replication link is greater than the one
* we are freeing removing the key, but we can&#39;t account for
* that otherwise we would never exit the loop.
*
* AOF and Output buffer memory will be freed eventually so
* we only care about memory used by the key space. */
// 只计算 dbDelete() 释放内存的大小
delta = (long long) zmalloc_used_memory();
dbDelete(db,keyobj);
delta -= (long long) zmalloc_used_memory();
mem_freed += delta;
server.stat_evictedkeys++;
// 将数据的删除通知所有的订阅客户端
notifyKeyspaceEvent(REDIS_NOTIFY_EVICTED, "evicted",
keyobj, db->id);
decrRefCount(keyobj);
keys_freed++; 
// 将从机回复空间中的数据及时发送给从机
/* When the memory to free starts to be big enough, we may
* start spending so much time here that is impossible to
* deliver data to the slaves fast enough, so we force the
* transmission here inside the loop. */
if (slaves) flushSlavesOutputBuffers();
}
} 
// 未能释放空间,且此时 redis 使用的内存大小依旧超额,失败返回
if (!keys_freed) return REDIS_ERR; /* nothing to free... */
}
return REDIS_OK;
}

적용 가능한 시나리오

몇 가지 전략의 적용 가능한 시나리오를 살펴보겠습니다.

1. allkeys-lru: 캐시에 대한 애플리케이션의 액세스가 거듭제곱 법칙 분포를 따르는 경우(즉, 비교적 핫 데이터가 있는 경우) ) 또는 애플리케이션의 캐시 액세스 분포를 잘 알지 못하기 때문에 allkeys-lru 전략을 선택할 수 있습니다.

2. allkeys-random: 애플리케이션이 캐시 키에 대한 액세스 확률이 동일하다면 이 전략을 사용할 수 있습니다.

3. 휘발성-ttl: 이 전략을 사용하면 어떤 키가 제거에 더 적합한지 Redis에 알릴 수 있습니다.

그리고 하나의 Redis 인스턴스를 캐시와 영구 저장소에 모두 적용할 때는 휘발성-lru 전략과 휘발성-랜덤 전략이 적합합니다. 하지만 두 개의 Redis 인스턴스를 사용해도 동일한 효과를 얻을 수 있다는 점은 가치가 있습니다. 언급할 점은 키 만료 시간을 설정하면 실제로 더 많은 메모리를 소비하므로 메모리를 더 효율적으로 사용하려면 allkeys-lru 전략을 사용하는 것이 좋습니다.

더 많은 Redis 지식을 알고 싶다면 redis 입문 튜토리얼 칼럼을 주목해 주세요.

위 내용은 Redis 데이터 제거 전략에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 CSDN에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
Redis : 기능과 기능을 탐색합니다Redis : 기능과 기능을 탐색합니다Apr 19, 2025 am 12:04 AM

Redis는 고속, 다양성 및 풍부한 데이터 구조로 인해 두드러집니다. 1) Redis는 문자열, 목록, 컬렉션, 해시 및 주문 컬렉션과 같은 데이터 구조를 지원합니다. 2) 메모리를 통해 데이터를 저장하고 RDB 및 AOF 지속성을 지원합니다. 3) Redis 6.0에서 시작하여 멀티 스레드 I/O 작업이 도입되어 동시 동시성 시나리오에서 성능이 향상되었습니다.

Redis는 SQL 또는 NOSQL 데이터베이스입니까? 대답이 설명되었습니다Redis는 SQL 또는 NOSQL 데이터베이스입니까? 대답이 설명되었습니다Apr 18, 2025 am 12:11 AM

redisisclassifiedasanoSqldatabaseBecauseItuseSakey-valuedatamodelinsteadofThraditionalRelationalDatabasemodel.Itoffersspeedandflexibility, makingIdealforreal-timeApplicationsandcaching, butitmaynotbesuitableforscenariosrequiringstrictaintetaintetaintetaintetaintetaintetaintegry

REDIS : 응용 프로그램 성능 및 확장 성 향상REDIS : 응용 프로그램 성능 및 확장 성 향상Apr 17, 2025 am 12:16 AM

Redis는 데이터를 캐싱하여 분산 잠금 및 데이터 지속성을 구현하여 응용 프로그램 성능 및 확장 성을 향상시킵니다. 1) 캐시 데이터 : Redis를 사용하여 데이터 액세스 속도를 향상시키기 위해 자주 액세스하는 데이터를 캐시합니다. 2) 분산 잠금 : Redis를 사용하여 분산 된 잠금 장치를 구현하여 분산 환경에서 작동의 보안을 보장합니다. 3) 데이터 지속성 : 데이터 손실을 방지하기위한 RDB 및 AOF 메커니즘을 통한 데이터 보안을 보장합니다.

Redis : 데이터 모델과 구조 탐색Redis : 데이터 모델과 구조 탐색Apr 16, 2025 am 12:09 AM

Redis의 데이터 모델 및 구조에는 5 가지 주요 유형이 포함됩니다. 1. 문자열 : 텍스트 또는 이진 데이터를 저장하는 데 사용되며 원자 연산을 지원합니다. 2. 목록 : 정렬 된 요소 컬렉션, 대기열 및 스택에 적합합니다. 세트 : 세트 작동을 지원하는 비 순차 고유 요소 세트. 4. 순서 세트 (SortedSet) : 순위에 적합한 점수가있는 고유 한 요소 세트. 5. 해시 테이블 (HASH) : 객체를 저장하는 데 적합한 키 값 쌍 모음.

REDIS : 데이터베이스 접근 방식을 분류합니다REDIS : 데이터베이스 접근 방식을 분류합니다Apr 15, 2025 am 12:06 AM

Redis의 데이터베이스 방법에는 메모리 인 데이터베이스 및 키 값 저장소가 포함됩니다. 1) Redis는 메모리에 데이터를 저장하고 빠르게 읽고 쓰고 있습니다. 2) 키 값 쌍을 사용하여 데이터를 저장하고 캐시 및 NOSQL 데이터베이스에 적합한 목록, 컬렉션, 해시 테이블 및 주문 컬렉션과 같은 복잡한 데이터 구조를 지원합니다.

왜 Redis를 사용합니까? 혜택과 장점왜 Redis를 사용합니까? 혜택과 장점Apr 14, 2025 am 12:07 AM

Redis는 빠른 성능, 풍부한 데이터 구조, 고 가용성 및 확장 성, 지속성 기능 및 광범위한 생태계 지원을 제공하기 때문에 강력한 데이터베이스 솔루션입니다. 1) 매우 빠른 성능 : Redis의 데이터는 메모리에 저장되며 동시성이 높고 대기 시간이 낮은 응용 프로그램에 적합한 빠른 읽기 및 쓰기 속도를 가지고 있습니다. 2) 풍부한 데이터 구조 : 다양한 시나리오에 적합한 목록, 컬렉션 등과 같은 여러 데이터 유형을 지원합니다. 3) 고 가용성 및 확장 성 : 마스터 슬레이브 복제 및 클러스터 모드를 지원하여 고 가용성 및 수평 확장 성을 달성합니다. 4) 지속성 및 데이터 보안 : 데이터 지속성은 RDB 및 AOF를 통해 달성되어 데이터 무결성 및 신뢰성을 보장합니다. 5) 광범위한 생태계 및 지역 사회 지원 : 거대한 생태계와 활동적인 커뮤니티,

NOSQL 이해 : Redis의 주요 기능NOSQL 이해 : Redis의 주요 기능Apr 13, 2025 am 12:17 AM

Redis의 주요 기능에는 속도, 유연성 및 풍부한 데이터 구조 지원이 포함됩니다. 1) 속도 : Redis는 메모리 내 데이터베이스이며, 읽기 및 쓰기 작업은 거의 순간적이며 캐시 및 세션 관리에 적합합니다. 2) 유연성 : 복잡한 데이터 처리에 적합한 문자열, 목록, 컬렉션 등과 같은 여러 데이터 구조를 지원합니다. 3) 데이터 구조 지원 : 다양한 비즈니스 요구에 적합한 문자열, 목록, 컬렉션, 해시 테이블 등을 제공합니다.

REDIS : 기본 기능을 식별합니다REDIS : 기본 기능을 식별합니다Apr 12, 2025 am 12:01 AM

Redis의 핵심 기능은 고성능 인 메모리 데이터 저장 및 처리 시스템입니다. 1) 고속 데이터 액세스 : Redis는 메모리에 데이터를 저장하고 마이크로 초 수준 읽기 및 쓰기 속도를 제공합니다. 2) 풍부한 데이터 구조 : 문자열, 목록, 컬렉션 등을 지원하며 다양한 응용 프로그램 시나리오에 적응합니다. 3) 지속성 : RDB 및 AOF를 통해 디스크에 데이터를 지속하십시오. 4) 구독 게시 : 메시지 대기열 또는 실시간 통신 시스템에서 사용할 수 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.