From 9b48a5896af6d1f3d81e0a6bf7f407992cdee2b7 Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Fri, 20 Aug 2010 14:04:26 -0700 Subject: [PATCH] add maxmemory_margin to allow for forcibly freeing more than the bare minimum, and making space for new entries. track the count of expired and forcibly expired items. --- src/config.c | 2 ++ src/redis.c | 12 +++++++++--- src/redis.h | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 329d2ce84..496d351b3 100644 --- a/src/config.c +++ b/src/config.c @@ -123,6 +123,8 @@ void loadServerConfig(char *filename) { server.maxclients = atoi(argv[1]); } else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) { server.maxmemory = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"maxmemory_margin") && argc == 2) { + server.maxmemory_margin = memtoll(argv[1],NULL); } else if (!strcasecmp(argv[0],"memory_pressure_selection") && argc == 2) { server.memory_pressure_selection = atoi(argv[1]); } else if (!strcasecmp(argv[0],"slaveof") && argc == 3) { diff --git a/src/redis.c b/src/redis.c index f5acc2d4e..b8e4d3191 100644 --- a/src/redis.c +++ b/src/redis.c @@ -471,6 +471,7 @@ void activeExpireCycle(void) { dbDelete(db,keyobj); decrRefCount(keyobj); expired++; + db->expired_count++; server.stat_expiredkeys++; } } @@ -734,6 +735,7 @@ void initServerConfig() { server.maxclients = 0; server.blpop_blocked_clients = 0; server.maxmemory = 0; + server.maxmemory_margin = 0; server.memory_pressure_selection = 3; server.vm_enabled = 0; server.vm_swap_file = zstrdup("/tmp/redis-%p.vm"); @@ -803,6 +805,8 @@ void initServer() { if (server.vm_enabled) server.db[j].io_keys = dictCreate(&keylistDictType,NULL); server.db[j].id = j; + server.db[j].expired_count = 0; + server.db[j].prematurely_expired_count = 0; } server.pubsub_channels = dictCreate(&keylistDictType,NULL); server.pubsub_patterns = listCreate(); @@ -1257,8 +1261,8 @@ sds genRedisInfoString(void) { keys = dictSize(server.db[j].dict); vkeys = dictSize(server.db[j].expires); if (keys || vkeys) { - info = sdscatprintf(info, "db%d:keys=%lld,expires=%lld\r\n", - j, keys, vkeys); + info = sdscatprintf(info, "db%d:keys=%lld,expires=%lld,expired=%lu,premature=%lu\r\n", + j, keys, vkeys, server.db[j].expired_count, server.db[j].prematurely_expired_count); } } return info; @@ -1317,7 +1321,7 @@ int tryFreeOneObjectFromFreelist(void) { * memory usage. */ void freeMemoryIfNeeded(void) { - while (server.maxmemory && zmalloc_used_memory() > server.maxmemory) { + while (server.maxmemory && zmalloc_used_memory() + server.maxmemory_margin > server.maxmemory) { int j, k, freed = 0; if (tryFreeOneObjectFromFreelist() == REDIS_OK) continue; @@ -1343,6 +1347,8 @@ void freeMemoryIfNeeded(void) { dictDelete(server.db[j].expires,minkey); dictDelete(server.db[j].dict,minkey); + server.db[j].expired_count++; + server.db[j].prematurely_expired_count++; } } if (!freed) return; /* nothing to free... */ diff --git a/src/redis.h b/src/redis.h index da02829fb..0a64bf5f9 100644 --- a/src/redis.h +++ b/src/redis.h @@ -260,6 +260,8 @@ typedef struct redisDb { dict *io_keys; /* Keys with clients waiting for VM I/O */ dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */ int id; + unsigned long expired_count; + unsigned long prematurely_expired_count; } redisDb; /* Client MULTI/EXEC state */ @@ -381,6 +383,7 @@ struct redisServer { int replstate; unsigned int maxclients; unsigned long long maxmemory; + unsigned long long maxmemory_margin; /* bytes to keep free for new data */ int memory_pressure_selection; /* # of candidates to choose from in freeMemoryIfNeeded(). */ unsigned int blpop_blocked_clients; unsigned int vm_blocked_clients; -- GitLab