Files
redis/tests/unit/lazyfree.tcl
debing.sunandGitHub a97cc53281 Fix timing issue in lazyfree test (#13926)
This test was introduced by https://github.com/redis/redis/issues/13853
We determine if the client is in blocked status, but if async flushdb is
completed before checking the blocked status, the test will fail.
So modify the test to only determine if `lazyfree_pending_objects` is
correct to ensure that flushdb is async, that is, the client must be
blocked.
2025-04-13 20:32:16 +08:00

201 lines
5.9 KiB
Tcl

start_server {tags {"lazyfree"}} {
test "UNLINK can reclaim memory in background" {
set orig_mem [s used_memory]
set args {}
for {set i 0} {$i < 100000} {incr i} {
lappend args $i
}
r sadd myset {*}$args
assert {[r scard myset] == 100000}
set peak_mem [s used_memory]
assert {[r unlink myset] == 1}
assert {$peak_mem > $orig_mem+1000000}
wait_for_condition 50 100 {
[s used_memory] < $peak_mem &&
[s used_memory] < $orig_mem*2
} else {
fail "Memory is not reclaimed by UNLINK"
}
}
test "FLUSHDB ASYNC can reclaim memory in background" {
# make the previous test is really done before sampling used_memory
wait_lazyfree_done r
set orig_mem [s used_memory]
set args {}
for {set i 0} {$i < 100000} {incr i} {
lappend args $i
}
r sadd myset {*}$args
assert {[r scard myset] == 100000}
set peak_mem [s used_memory]
r flushdb async
assert {$peak_mem > $orig_mem+1000000}
wait_for_condition 50 100 {
[s used_memory] < $peak_mem &&
[s used_memory] < $orig_mem*2
} else {
fail "Memory is not reclaimed by FLUSHDB ASYNC"
}
}
test "lazy free a stream with all types of metadata" {
# make the previous test is really done before doing RESETSTAT
wait_for_condition 50 100 {
[s lazyfree_pending_objects] == 0
} else {
fail "lazyfree isn't done"
}
r config resetstat
r config set stream-node-max-entries 5
for {set j 0} {$j < 1000} {incr j} {
if {rand() < 0.9} {
r xadd stream * foo $j
} else {
r xadd stream * bar $j
}
}
r xgroup create stream mygroup 0
set records [r xreadgroup GROUP mygroup Alice COUNT 2 STREAMS stream >]
r xdel stream [lindex [lindex [lindex [lindex $records 0] 1] 1] 0]
r xack stream mygroup [lindex [lindex [lindex [lindex $records 0] 1] 0] 0]
r unlink stream
# make sure it was lazy freed
wait_for_condition 50 100 {
[s lazyfree_pending_objects] == 0
} else {
fail "lazyfree isn't done"
}
assert_equal [s lazyfreed_objects] 1
} {} {needs:config-resetstat}
test "lazy free a stream with deleted cgroup" {
r config resetstat
r xadd s * a b
r xgroup create s bla $
r xgroup destroy s bla
r unlink s
# make sure it was not lazy freed
wait_for_condition 50 100 {
[s lazyfree_pending_objects] == 0
} else {
fail "lazyfree isn't done"
}
assert_equal [s lazyfreed_objects] 0
} {} {needs:config-resetstat}
test "FLUSHALL SYNC optimized to run in bg as blocking FLUSHALL ASYNC" {
set num_keys 1000
r config resetstat
# Verify at start there are no lazyfree pending objects
assert_equal [s lazyfree_pending_objects] 0
# Fillup DB with items
populate $num_keys
# Run FLUSHALL SYNC command, optimized as blocking ASYNC
r flushall
# Verify all keys counted as lazyfreed
assert_equal [s lazyfreed_objects] $num_keys
}
test "Run consecutive blocking FLUSHALL ASYNC successfully" {
r config resetstat
set rd [redis_deferring_client]
# Fillup DB with items
r set x 1
r set y 2
$rd write "FLUSHALL\r\nFLUSHALL\r\nFLUSHDB\r\n"
$rd flush
assert_equal [$rd read] {OK}
assert_equal [$rd read] {OK}
assert_equal [$rd read] {OK}
assert_equal [s lazyfreed_objects] 2
$rd close
}
test "FLUSHALL SYNC in MULTI not optimized to run as blocking FLUSHALL ASYNC" {
r config resetstat
# Fillup DB with items
r set x 11
r set y 22
# FLUSHALL SYNC in multi
r multi
r flushall
r exec
# Verify flushall not run as lazyfree
assert_equal [s lazyfree_pending_objects] 0
assert_equal [s lazyfreed_objects] 0
}
test "Client closed in the middle of blocking FLUSHALL ASYNC" {
set num_keys 100000
r config resetstat
# Fillup DB with items
populate $num_keys
# close client in the middle of ongoing Blocking FLUSHALL ASYNC
set rd [redis_deferring_client]
$rd flushall
$rd close
# Wait to verify all keys counted as lazyfreed
wait_for_condition 50 100 {
[s lazyfreed_objects] == $num_keys
} else {
fail "Unexpected number of lazyfreed_objects: [s lazyfreed_objects]"
}
}
test "Pending commands in querybuf processed once unblocking FLUSHALL ASYNC" {
r config resetstat
set rd [redis_deferring_client]
# Fillup DB with items
r set x 1
r set y 2
$rd write "FLUSHALL\r\nPING\r\n"
$rd flush
assert_equal [$rd read] {OK}
assert_equal [$rd read] {PONG}
assert_equal [s lazyfreed_objects] 2
$rd close
}
test "Unblocks client blocked on lazyfree via REPLICAOF command" {
r config resetstat
set rd [redis_deferring_client]
populate 50000 ;# Just to make flushdb async slower
$rd flushdb
# Verify flushdb run as lazyfree
wait_for_condition 50 100 {
[s lazyfree_pending_objects] > 0 ||
[s lazyfreed_objects] > 0
} else {
fail "FLUSHDB didn't run as lazyfree"
}
# Test that slaveof command unblocks clients without assertion failure
r slaveof 127.0.0.1 0
assert_equal [$rd read] {OK}
$rd close
r ping
r slaveof no one
} {OK} {external:skip}
}