Skip to content

Commit

Permalink
update codes to align with maxmemory-reserved config parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
hwware committed Feb 3, 2025
1 parent 3e2f561 commit 698fe0a
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 91 deletions.
48 changes: 19 additions & 29 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2490,45 +2490,36 @@ static int updateReplBacklogSize(const char **err) {
return 1;
}

static int updateKeyEvictionMemory(const char **err) {
UNUSED(err);
static int updateMaxmemoryReserved(const char **err) {
if (server.maxmemory) {
if (!server.key_eviction_memory) {
serverLog(LL_WARNING,
"WARNING: current maxmemory value is not 0, the new key-eviction-memory value set via CONFIG SET (%llu) is "
"0. The new key-eviction-memory value is set to equal to current maxmemory (%llu) ",
server.key_eviction_memory, server.maxmemory);
server.key_eviction_memory = server.maxmemory;
} else if (server.key_eviction_memory > server.maxmemory) {
serverLog(LL_WARNING,
"WARNING: the new key-eviction-memory value set via CONFIG SET (%llu) is greater than current maxmemory, "
"The new key-eviction-memory value is set to equal to current maxmemory (%llu) ",
server.key_eviction_memory, server.maxmemory);
server.key_eviction_memory = server.maxmemory;
if (server.maxmemory < server.maxmemory_reserved) {
*err = "The maxmemory value is smaller than the new reserved memory buffer set via CONFIG SET";
return 0;
}
server.key_eviction_memory = server.maxmemory - server.maxmemory_reserved;
size_t used = zmalloc_used_memory() - freeMemoryGetNotCountedMemory();
if (server.key_eviction_memory < used) {
serverLog(LL_WARNING,
"WARNING: the new key-eviction-memorym 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.key_eviction_memory, used);
"WARNING: the difference between memory usage and maxmemory is less than reserved memory. "
"This will result in key eviction depending on the maxmemory-policy. But server can still accept new write commands.");
}
startEvictionTimeProc();
} else {
if (server.key_eviction_memory) {
serverLog(LL_WARNING,
"WARNING: current maxmemory value is 0, the new key-eviction-memory value set via CONFIG SET (%llu) is "
"greater than 0. The new key-eviction-memory value is invalid, and its value is set to 0 ",
server.key_eviction_memory);
if (server.maxmemory_reserved) {
*err = "Current maxmemory value is 0, the new reserved memory buffer value is invalid";
return 0;
}
server.key_eviction_memory = 0;
}
return 1;
}

static int updateMaxmemory(const char **err) {
UNUSED(err);
if (server.maxmemory) {
if (server.maxmemory < server.maxmemory_reserved) {
*err = "The new maxmemory value set via CONFIG SET is smaller than the existing reserved memory buffer";
return 0;
}
size_t used = zmalloc_used_memory() - freeMemoryGetNotCountedMemory();
if (server.maxmemory < used) {
serverLog(LL_WARNING,
Expand All @@ -2537,12 +2528,11 @@ static int updateMaxmemory(const char **err) {
"depending on the maxmemory-policy.",
server.maxmemory, used);
}
if (!server.key_eviction_memory || server.key_eviction_memory > server.maxmemory) {
server.key_eviction_memory = server.maxmemory;
}
server.key_eviction_memory = server.maxmemory - server.maxmemory_reserved;
startEvictionTimeProc();
} else {
server.key_eviction_memory = 0;
server.maxmemory_reserved = 0;
server.key_eviction_memory = 0;
}
return 1;
}
Expand Down Expand Up @@ -3359,7 +3349,7 @@ standardConfig static_configs[] = {

/* Unsigned Long Long configs */
createULongLongConfig("maxmemory", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.maxmemory, 0, MEMORY_CONFIG, NULL, updateMaxmemory),
createULongLongConfig("key-eviction-memory", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.key_eviction_memory, 0, MEMORY_CONFIG, NULL, updateKeyEvictionMemory),
createULongLongConfig("maxmemory-reserved", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.maxmemory_reserved, 0, MEMORY_CONFIG, NULL, updateMaxmemoryReserved),
createULongLongConfig("cluster-link-sendbuf-limit", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.cluster_link_msg_queue_limit_bytes, 0, MEMORY_CONFIG, NULL, NULL),

/* Size_t configs */
Expand Down
6 changes: 4 additions & 2 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2764,9 +2764,11 @@ void initServer(void) {
resetReplicationBuffer();

if (server.maxmemory) {
if (!server.key_eviction_memory || server.key_eviction_memory > server.maxmemory) {
server.key_eviction_memory = server.maxmemory;
if (server.maxmemory < server.maxmemory_reserved) {
serverLog(LL_WARNING, "Failed to config reserved memory buffer, which is greater than maxmemory.");
exit(1);
}
server.key_eviction_memory = server.maxmemory - server.maxmemory_reserved;
} else {
server.key_eviction_memory = 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,7 @@ struct valkeyServer {
/* Limits */
unsigned int maxclients; /* Max number of simultaneous clients */
unsigned long long maxmemory; /* Max number of memory bytes to use */
unsigned long long maxmemory_reserved; /* Memory bytes to be away from maxmemory*/
unsigned long long key_eviction_memory; /* Memory bytes to begin the key eviction process */
ssize_t maxmemory_clients; /* Memory limit for total client buffers */
int maxmemory_policy; /* Policy for key eviction */
Expand Down
92 changes: 36 additions & 56 deletions tests/unit/maxmemory.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ start_server {tags {"maxmemory external:skip"}} {
r setex [randomKey] 10000 x
}
assert {[s used_memory] < ($limit+4096)}
r config set maxmemory 0
}
}

Expand Down Expand Up @@ -217,7 +216,6 @@ start_server {tags {"maxmemory external:skip"}} {
} else {
assert {$err == 1}
}
r config set maxmemory 0
}
}

Expand Down Expand Up @@ -263,90 +261,72 @@ start_server {tags {"maxmemory external:skip"}} {
for {set j 0} {$j < $numkeys} {incr j 2} {
assert {[r exists "key:$j"]}
}
r config set maxmemory 0
}
}

test "key-eviction-memory could change with maxmemory update" {
test "enable maxmemory-reserved, available memory could change with maxmemory update" {
# make sure to start with a blank instance
r flushall
# we set maxmemory as 0, and we expect key-eviction-memory as 0 too.
# we set maxmemory as 0, and we expect maxmemory-reserved as 0 too.
r config set maxmemory 0
assert_equal 0 [lindex [r config get maxmemory] 1]
assert_equal 0 [lindex [r config get key-eviction-memory] 1]
# we increase maxmemory, and we expect key-eviction-memory value is increased too.
r config set maxmemory 10mb
set key_eviction_memory [lindex [r config get key-eviction-memory] 1]
assert_equal [lindex [r config get maxmemory] 1] $key_eviction_memory
# we increase maxmemory a little bit, but we expect key-eviction-memory value no change.
r config set maxmemory 11mb
assert_equal $key_eviction_memory [lindex [r config get key-eviction-memory] 1]
assert_morethan [lindex [r config get maxmemory] 1] [lindex [r config get key-eviction-memory] 1]
# we decrease maxmemory lower than key-eviction-memory, thus we expect key-eviction-memory value decrease to maxmemory value.
r config set maxmemory 6mb
assert_equal [lindex [r config get maxmemory] 1] [lindex [r config get key-eviction-memory] 1]
# we decrease maxmemory to 0, and we expect key-eviction-memory value decrease to 0 too.
r config set maxmemory 0
assert_equal 0 [lindex [r config get maxmemory] 1]
assert_equal 0 [lindex [r config get key-eviction-memory] 1]
}

test "key-eviction-memory update test" {
# make sure to start with a blank instance
r flushall
# If maxmemory is not 0, and key-eviction-memory is set to 0, we expect the key-eviction-memory equal to maxmemory
r config set maxmemory 10mb
r config set key-eviction-memory 0
assert_equal [lindex [r config get maxmemory] 1] [lindex [r config get key-eviction-memory] 1]
# we increase key-eviction-memory, but its value is still less than maxmemory.
r config set key-eviction-memory 5mb
assert_morethan [lindex [r config get maxmemory] 1] [lindex [r config get key-eviction-memory] 1]
# we increase key-eviction-memory more than maxmemory, but we expect its value is equal to maxmemory.
r config set key-eviction-memory 10mb
assert_equal [lindex [r config get maxmemory] 1] [lindex [r config get key-eviction-memory] 1]
r config set maxmemory 0
assert_equal 0 [lindex [r config get maxmemory-reserved] 1]
# we increase maxmemory, and we expect more memory available (key_eviction_memory field value increases too).
r config set maxmemory 10000000
assert_equal 0 [lindex [r config get maxmemory-reserved] 1]
set info_memory [r info memory]
assert_equal [getInfoProperty $info_memory key_eviction_memory] 10000000
# we set maxmemory-reserved as non-zero value first
r config set maxmemory-reserved 4000000
set info_memory [r info memory]
assert_equal [getInfoProperty $info_memory key_eviction_memory] 6000000
# we decrease maxmemory, and we expect less memory available (key_eviction_memory field value decreases too).
r config set maxmemory 8000000
set info_memory [r info memory]
assert_equal [getInfoProperty $info_memory key_eviction_memory] 4000000
}


foreach policy {
allkeys-random allkeys-lru allkeys-lfu volatile-lru volatile-lfu volatile-random volatile-ttl
} {
test "key-eviction-memory - test eviction key number with policy ($policy) and different key-eviction-memory value" {
test "enable maxmemory-reserved, test eviction key number with policy ($policy) and different maxmemory value" {
r flushall
r config set maxmemory 0
# make sure to start with a blank instance
set num_eviction_key_init [s evicted_keys]
set used 1134728
set limit_maxmemory [expr {$used+100*1024}]
set limit_key_eviction_memory_threshold1 [expr {$used+70*1024}]
set limit_key_eviction_memory_threshold2 [expr {$used+40*1024}]
r config set maxmemory $limit_maxmemory
set used 1165448
set limit_maxmemory_value1 [expr {$used+40*1024}]
set limit_maxmemory_value2 [expr {$used+70*1024}]
set limit_maxmemory_value3 [expr {$used+100*1024}]
r config set maxmemory $limit_maxmemory_value1
r config set maxmemory-policy $policy
r config set maxmemory-reserved 30720
set numkeys 5000
for {set j 0} {$j < $numkeys} {incr j} {
catch {r set $j $j EX 10000}
}
set num_eviction_key_maxmemory [s evicted_keys]
set diff_num_key_eviction_one [expr {$num_eviction_key_maxmemory - $num_eviction_key_init}]
set num_eviction_key_maxmemory_1 [s evicted_keys]
set diff_num_key_eviction_one [expr {$num_eviction_key_maxmemory_1 - $num_eviction_key_init}]
r flushall
r config set key-eviction-memory $limit_key_eviction_memory_threshold1
r config set maxmemory $limit_maxmemory_value2
for {set j 0} {$j < $numkeys} {incr j} {
catch {r set $j $j EX 10000}
}
set num_eviction_key_threshold1 [s evicted_keys]
set diff_num_key_eviction_two [expr {$num_eviction_key_threshold1 - $num_eviction_key_maxmemory}]
set num_eviction_key_maxmemory_2 [s evicted_keys]
set diff_num_key_eviction_two [expr {$num_eviction_key_maxmemory_2 - $num_eviction_key_maxmemory_1}]
r flushall
r config set key-eviction-memory $limit_key_eviction_memory_threshold2
r config set maxmemory $limit_maxmemory_value3
for {set j 0} {$j < $numkeys} {incr j} {
catch {r set $j $j EX 10000}
}
set num_eviction_key_threshold2 [s evicted_keys]
set diff_num_key_eviction_three [expr {$num_eviction_key_threshold2 - $num_eviction_key_threshold1}]
assert_morethan $diff_num_key_eviction_three $diff_num_key_eviction_two
assert_morethan $diff_num_key_eviction_two $diff_num_key_eviction_one
set num_eviction_key_maxmemory_3 [s evicted_keys]
set diff_num_key_eviction_three [expr {$num_eviction_key_maxmemory_3 - $num_eviction_key_maxmemory_2}]
assert_morethan $diff_num_key_eviction_two $diff_num_key_eviction_three
assert_morethan $diff_num_key_eviction_one $diff_num_key_eviction_two
r flushall
r config set maxmemory 0
}
}
}
}
}
# Calculate query buffer memory of slave
proc slave_query_buffer {srv} {
Expand Down
1 change: 0 additions & 1 deletion tests/unit/memefficiency.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ run_solo {defrag} {
r config set latency-monitor-threshold 5
r latency reset
r config set maxmemory 110mb ;# prevent further eviction (not to fail the digest test)
r config set key-eviction-memory 110mb
set digest [debug_digest]
catch {r config set activedefrag yes} e
if {[r config get activedefrag] eq "activedefrag yes"} {
Expand Down
6 changes: 3 additions & 3 deletions valkey.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1270,11 +1270,11 @@ acllog-max-len 128
#
# maxmemory-policy noeviction

# `key-eviction-memory` defines a "soft" maxmemory threshold as the `maxmemory` limit.
# When memory usage exceeds this key-eviction-memory, Valkey begins proactive key eviction. However, exceeding this
# `maxmemory-reserved` defines a fix amount of reserved maxmemory away from maxmemory.
# When the difference between memory usage and maxmemory is less than it, Valkey begins proactive key eviction. However, exceeding this
# threshold does not immediately reject new write commands; only the hard `maxmemory` limit will do so.
#
# key-eviction-memory <bytes>
# maxmemory-reserved <bytes>

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
Expand Down

0 comments on commit 698fe0a

Please sign in to comment.