Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add maxmemory-reserved-scale parameter to evict keys earlier if maxmemory parameter is set #89

Open
wants to merge 4 commits into
base: unstable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions redis.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,14 @@ acllog-max-len 128
# in the system. It's a tradeoff between memory, CPU and latency.
#
# active-expire-effort 1
#
# It allows the redis to evict keys earlier. The value of this parameter represents
# percent of the maxmemory value. It means how much memory the redis instance want to hold
# not to store the data.
# Default is 0, and the value could be set between 10 to 60.
#
# maxmemory-reserved-scale 0


############################# LAZY FREEING ####################################

Expand Down
15 changes: 15 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2463,13 +2463,27 @@ static int updateReplBacklogSize(const char **err) {
return 1;
}

static int updateMaxmemoryReserved(const char **err) {
UNUSED(err);
if (server.maxmemory_reserved_scale) {
if (server.maxmemory_reserved_scale < 10) {
server.maxmemory_reserved_scale = 10;
} else if (server.maxmemory_reserved_scale > 60) {
server.maxmemory_reserved_scale = 60;
}
}
server.maxmemory_available= (unsigned long long)server.maxmemory / 100.0 * (100 - server.maxmemory_reserved_scale);
return 1;
}

static int updateMaxmemory(const char **err) {
UNUSED(err);
if (server.maxmemory) {
size_t used = zmalloc_used_memory()-freeMemoryGetNotCountedMemory();
if (server.maxmemory < used) {
serverLog(LL_WARNING,"WARNING: the new maxmemory value set via CONFIG SET (%llu) is smaller than the current memory usage (%zu). This will result in key eviction and/or the inability to accept new write commands depending on the maxmemory-policy.", server.maxmemory, used);
}
server.maxmemory_available= (unsigned long long)server.maxmemory / 100.0 * (100 - server.maxmemory_reserved_scale);
startEvictionTimeProc();
}
return 1;
Expand Down Expand Up @@ -3124,6 +3138,7 @@ standardConfig static_configs[] = {
createIntConfig("lfu-decay-time", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.lfu_decay_time, 1, INTEGER_CONFIG, NULL, NULL),
createIntConfig("replica-priority", "slave-priority", MODIFIABLE_CONFIG, 0, INT_MAX, server.slave_priority, 100, INTEGER_CONFIG, NULL, NULL),
createIntConfig("repl-diskless-sync-delay", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.repl_diskless_sync_delay, 5, INTEGER_CONFIG, NULL, NULL),
createIntConfig("maxmemory-reserved-scale", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_reserved_scale, 0, INTEGER_CONFIG, NULL, updateMaxmemoryReserved),
createIntConfig("maxmemory-samples", NULL, MODIFIABLE_CONFIG, 1, INT_MAX, server.maxmemory_samples, 5, INTEGER_CONFIG, NULL, NULL),
createIntConfig("maxmemory-eviction-tenacity", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_eviction_tenacity, 10, INTEGER_CONFIG, NULL, NULL),
createIntConfig("timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.maxidletime, 0, INTEGER_CONFIG, NULL, NULL), /* Default client timeout: infinite */
Expand Down
28 changes: 22 additions & 6 deletions src/evict.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,11 @@ int getMaxmemoryState(size_t *total, size_t *logical, size_t *tofree, float *lev
if (level) *level = 0;
return C_OK;
}
if (mem_reported <= server.maxmemory && !level) return C_OK;

if (server.maxmemory_reserved_scale) {
if (mem_reported <= server.maxmemory_available && !level) return C_OK;
} else if (mem_reported <= server.maxmemory && !level)
return C_OK;

/* Remove the size of slaves output buffers and AOF buffer from the
* count of used memory. */
Expand All @@ -416,15 +420,27 @@ int getMaxmemoryState(size_t *total, size_t *logical, size_t *tofree, float *lev
mem_used = (mem_used > overhead) ? mem_used-overhead : 0;

/* Compute the ratio of memory usage. */
if (level) *level = (float)mem_used / (float)server.maxmemory;
if (level) {
if (server.maxmemory_reserved_scale)
*level = (float)mem_used / (float)server.maxmemory_available;
else
*level = (float)mem_used / (float)server.maxmemory;
}

if (mem_reported <= server.maxmemory) return C_OK;
if (server.maxmemory_reserved_scale) {
if (mem_reported <= server.maxmemory_available) return C_OK;
} else if (mem_reported <= server.maxmemory) return C_OK;

/* Check if we are still over the memory limit. */
if (mem_used <= server.maxmemory) return C_OK;
if (server.maxmemory_reserved_scale) {
if (mem_used <= server.maxmemory_available) return C_OK;
} else if (mem_used <= server.maxmemory) return C_OK;

/* Compute how much memory we need to free. */
mem_tofree = mem_used - server.maxmemory;
if (server.maxmemory_reserved_scale) {
mem_tofree = mem_used - server.maxmemory_available;
} else
mem_tofree = mem_used - server.maxmemory;

if (logical) *logical = mem_used;
if (tofree) *tofree = mem_tofree;
Expand Down Expand Up @@ -547,7 +563,7 @@ int performEvictions(void) {
long long delta;
int slaves = listLength(server.slaves);
int result = EVICT_FAIL;

if (getMaxmemoryState(&mem_reported,NULL,&mem_tofree,NULL) == C_OK) {
result = EVICT_OK;
goto update_metrics;
Expand Down
11 changes: 11 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2537,6 +2537,9 @@ void initServer(void) {
server.reply_buffer_resizing_enabled = 1;
server.client_mem_usage_buckets = NULL;
resetReplicationBuffer();
if (server.maxmemory) {
server.maxmemory_available = (unsigned long long)server.maxmemory / 100.0 * (100 - server.maxmemory_reserved_scale);
}

/* Make sure the locale is set on startup based on the config file. */
if (setlocale(LC_COLLATE,server.locale_collate) == NULL) {
Expand Down Expand Up @@ -5521,6 +5524,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
char used_memory_scripts_hmem[64];
char used_memory_rss_hmem[64];
char maxmemory_hmem[64];
char maxmemory_available_hmem[64];
size_t zmalloc_used = zmalloc_used_memory();
size_t total_system_mem = server.system_memory_size;
const char *evict_policy = evictPolicyToString();
Expand All @@ -5543,6 +5547,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
bytesToHuman(used_memory_scripts_hmem,sizeof(used_memory_scripts_hmem),mh->lua_caches + mh->functions_caches);
bytesToHuman(used_memory_rss_hmem,sizeof(used_memory_rss_hmem),server.cron_malloc_stats.process_rss);
bytesToHuman(maxmemory_hmem,sizeof(maxmemory_hmem),server.maxmemory);
bytesToHuman(maxmemory_available_hmem,sizeof(maxmemory_available_hmem),server.maxmemory_available);

if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
Expand Down Expand Up @@ -5579,6 +5584,9 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
"maxmemory:%lld\r\n"
"maxmemory_human:%s\r\n"
"maxmemory_policy:%s\r\n"
"maxmemory_reserved_scale:%d\r\n"
"maxmemory_available:%lld\r\n"
"maxmemory_available_human:%s\r\n"
"allocator_frag_ratio:%.2f\r\n"
"allocator_frag_bytes:%zu\r\n"
"allocator_rss_ratio:%.2f\r\n"
Expand Down Expand Up @@ -5630,6 +5638,9 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
server.maxmemory,
maxmemory_hmem,
evict_policy,
server.maxmemory_reserved_scale,
server.maxmemory_available,
maxmemory_available_hmem,
mh->allocator_frag,
mh->allocator_frag_bytes,
mh->allocator_rss,
Expand Down
2 changes: 2 additions & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,8 @@ struct redisServer {
ssize_t maxmemory_clients; /* Memory limit for total client buffers */
int maxmemory_policy; /* Policy for key eviction */
int maxmemory_samples; /* Precision of random sampling */
int maxmemory_reserved_scale;
unsigned long long maxmemory_available;
int maxmemory_eviction_tenacity;/* Aggressiveness of eviction processing */
int lfu_log_factor; /* LFU logarithmic counter factor. */
int lfu_decay_time; /* LFU counter decay factor. */
Expand Down