summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobey Pointer <robey@twitter.com>2010-08-20 14:04:26 -0700
committerRobey Pointer <robey@twitter.com>2010-08-20 14:04:26 -0700
commit9b48a5896af6d1f3d81e0a6bf7f407992cdee2b7 (patch)
tree69d4102ce9dfea012ff6231e8d92c16bc910a0a0
parent30f0fd8f9f427c73f200a9cf1fd4b2425528b04d (diff)
downloadredis-9b48a5896af6d1f3d81e0a6bf7f407992cdee2b7.tar.gz
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.
-rw-r--r--src/config.c2
-rw-r--r--src/redis.c12
-rw-r--r--src/redis.h3
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;