From 7548400125beb7f3c3c1ba1bdb40cc90b6e34e44 Mon Sep 17 00:00:00 2001 From: Scott Lasley Date: Thu, 7 May 2026 08:10:59 -0400 Subject: [PATCH 1/3] Update replication.tcl #15177 Remove "$replica config set repl-diskless-load yes" line so tests will pass for redis 8.6.3 --- tests/integration/replication.tcl | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/replication.tcl b/tests/integration/replication.tcl index e90c30c2ca7..0309099428b 100644 --- a/tests/integration/replication.tcl +++ b/tests/integration/replication.tcl @@ -1888,7 +1888,6 @@ foreach type {script function} { $master config set repl-diskless-sync-delay 0 # Set small client output buffer limit to trigger fullsync quickly $master config set client-output-buffer-limit "replica 1k 1k 0" - $replica config set repl-diskless-load yes $replica config set busy-reply-threshold 1 ;# script timeout in 1 ms # Load function From 8b79d973d15cc773546793b035b9b870e0c0d73c Mon Sep 17 00:00:00 2001 From: "debing.sun" Date: Mon, 30 Mar 2026 19:50:47 +0800 Subject: [PATCH 2/3] Test tcp deadlock fixes (#14946) This fix follows #14667 and #14886 Several tests pipelined large numbers of commands on deferring clients without draining replies. That can fill buffers and stall progress. Fix by draining replies every 500 pipelined requests to avoid TCP stalls. --------- Co-authored-by: oranagra --- .../cluster/tests/17-diskless-load-swapdb.tcl | 9 +++++--- tests/helpers/gen_write_load.tcl | 23 +++++++++++++++++-- tests/unit/memefficiency.tcl | 13 +++++++---- tests/unit/type/set.tcl | 17 +++++++++++++- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/tests/cluster/tests/17-diskless-load-swapdb.tcl b/tests/cluster/tests/17-diskless-load-swapdb.tcl index cb81b9fdbd0..b25db393098 100644 --- a/tests/cluster/tests/17-diskless-load-swapdb.tcl +++ b/tests/cluster/tests/17-diskless-load-swapdb.tcl @@ -54,9 +54,12 @@ test "Main db not affected when fail to diskless load" { set rd [redis_deferring_client redis $master_id] for {set j 0} {$j < $num} {incr j} { $rd set $j $value - } - for {set j 0} {$j < $num} {incr j} { - $rd read + + if {($j + 1) % 500 == 0} { + for {set i 0} {$i < 500} {incr i} { + $rd read + } + } } # Start the replica again diff --git a/tests/helpers/gen_write_load.tcl b/tests/helpers/gen_write_load.tcl index 7b4975c61a9..60d954e5dbf 100644 --- a/tests/helpers/gen_write_load.tcl +++ b/tests/helpers/gen_write_load.tcl @@ -22,13 +22,18 @@ proc gen_write_load {host port seconds tls {key ""} {size 0} {sleep 0}} { set start_time [clock seconds] set r [redis $host $port 1 $tls] $r client setname LOAD_HANDLER - catch {$r select 9} ;# select 9 will fail in cluster mode + $r read + catch { + $r select 9 + $r read + } ;# select 9 will fail in cluster mode # fixed size value if {$size != 0} { set value [string repeat "x" $size] } + set count 0 while 1 { if {$size == 0} { set value [expr rand()] @@ -39,13 +44,27 @@ proc gen_write_load {host port seconds tls {key ""} {size 0} {sleep 0}} { } else { $r set $key $value } + + incr count + if {$count % 500 == 0} { + for {set i 0} {$i < 500} {incr i} { + $r read + } + } + if {[clock seconds]-$start_time > $seconds} { - exit 0 + break } if {$sleep ne 0} { after $sleep } } + + # Read remaining replies + for {set i 0} {$i < $count} {incr i} { + $r read + } + exit 0 } gen_write_load [lindex $argv 0] [lindex $argv 1] [lindex $argv 2] [lindex $argv 3] [lindex $argv 4] [lindex $argv 5] [lindex $argv 6] diff --git a/tests/unit/memefficiency.tcl b/tests/unit/memefficiency.tcl index 123bf3751c8..663a6098fca 100644 --- a/tests/unit/memefficiency.tcl +++ b/tests/unit/memefficiency.tcl @@ -24,9 +24,12 @@ proc test_memory_efficiency {range} { incr written [string length $key] incr written [string length $val] incr written 2 ;# A separator is the minimum to store key-value data. - } - for {set j 0} {$j < 10000} {incr j} { - $rd read ; # Discard replies + + if {($j + 1) % 500 == 0} { + for {set i 0} {$i < 500} {incr i} { + $rd read ; # Discard replies + } + } } set current_mem [s used_memory] @@ -352,7 +355,7 @@ run_solo {defrag} { # create big keys with 10k items # Use batching to avoid TCP deadlock set rd [redis_deferring_client] - set batch_size 1000 + set batch_size 100 for {set j 0} {$j < 10000} {incr j} { $rd hset bighash $j [concat "asdfasdfasdf" $j] $rd lpush biglist [concat "asdfasdfasdf" $j] @@ -925,7 +928,7 @@ run_solo {defrag} { $rd lpush biglist2 $val incr count - discard_replies_every $rd $count 10000 20000 + discard_replies_every $rd $count 1000 2000 } # create some fragmentation diff --git a/tests/unit/type/set.tcl b/tests/unit/type/set.tcl index 054c9784e84..5c38056433f 100644 --- a/tests/unit/type/set.tcl +++ b/tests/unit/type/set.tcl @@ -1026,7 +1026,22 @@ foreach type {single multiple single_multiple} { break } } - r srem $myset {*}$members + r deferred 1 + set count 0 + foreach m $members { + r srem $myset $m + incr count + if {$count == 500} { + for {set i 0} {$i < 500} {incr i} { + r read + } + set count 0 + } + } + for {set i 0} {$i < $count} {incr i} { + r read + } + r deferred 0 } proc verify_rehashing_completed_key {myset table_size keys} { From 7792a32aa5b6b05018af59668440b92044b4eae4 Mon Sep 17 00:00:00 2001 From: Vitah Lin Date: Thu, 26 Mar 2026 14:59:17 +0800 Subject: [PATCH 3/3] Fix potential TCP deadlock in Active defrag IDMP streams test (#14886) The IDMP streams defrag test sends all commands (100k) before reading any replies, which can cause TCP deadlock when buffers fill up. Fix by batching writes and reads (1000 iterations per batch), consistent with the approach already used in the script defrag test above. --- tests/unit/memefficiency.tcl | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/unit/memefficiency.tcl b/tests/unit/memefficiency.tcl index 663a6098fca..0ab12c6c7e4 100644 --- a/tests/unit/memefficiency.tcl +++ b/tests/unit/memefficiency.tcl @@ -605,15 +605,27 @@ run_solo {defrag} { # Populate memory with interleaving IDMP stream-key pattern of same size set dummy_iid "[string repeat x 400]" set rd [redis_deferring_client] + + # Use batching to avoid TCP deadlock + set batch_size 1000 for {set j 0} {$j < $n} {incr j} { set producer_id "producer[expr {$j % 10}]" set iid "$dummy_iid[format "%06d" $j]" $rd xadd idmpstream IDMP $producer_id $iid * field value $rd set k$j $iid + + if {($j + 1) % $batch_size == 0} { + for {set i 0} {$i < [expr {$batch_size * 2}]} {incr i} { + $rd read + } + } } - for {set j 0} {$j < [expr {$n * 2}]} {incr j} { - $rd read ; # Discard replies + # Read remaining responses + set remaining [expr {($n % $batch_size) * 2}] + for {set j 0} {$j < $remaining} {incr j} { + $rd read } + after 120 ;# serverCron only updates the info once in 100ms if {$::verbose} { puts "used [s allocator_allocated]" @@ -623,7 +635,7 @@ run_solo {defrag} { } assert_lessthan [s allocator_frag_ratio] 1.05 - # Verify IDMP structures were created + # Verify IDMP structures were created set idmp_info [r xinfo stream idmpstream full] set num_producers [dict get $idmp_info pids-tracked] set num_entries [dict get $idmp_info iids-tracked]