replication.tcl 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. proc log_file_matches {log pattern} {
  2. set fp [open $log r]
  3. set content [read $fp]
  4. close $fp
  5. string match $pattern $content
  6. }
  7. start_server {tags {"repl network external:skip"}} {
  8. set slave [srv 0 client]
  9. set slave_host [srv 0 host]
  10. set slave_port [srv 0 port]
  11. set slave_log [srv 0 stdout]
  12. start_server {} {
  13. set master [srv 0 client]
  14. set master_host [srv 0 host]
  15. set master_port [srv 0 port]
  16. # Configure the master in order to hang waiting for the BGSAVE
  17. # operation, so that the slave remains in the handshake state.
  18. $master config set repl-diskless-sync yes
  19. $master config set repl-diskless-sync-delay 1000
  20. # Use a short replication timeout on the slave, so that if there
  21. # are no bugs the timeout is triggered in a reasonable amount
  22. # of time.
  23. $slave config set repl-timeout 5
  24. # Start the replication process...
  25. $slave slaveof $master_host $master_port
  26. test {Slave enters handshake} {
  27. wait_for_condition 50 1000 {
  28. [string match *handshake* [$slave role]]
  29. } else {
  30. fail "Replica does not enter handshake state"
  31. }
  32. }
  33. # But make the master unable to send
  34. # the periodic newlines to refresh the connection. The slave
  35. # should detect the timeout.
  36. $master debug sleep 10
  37. test {Slave is able to detect timeout during handshake} {
  38. wait_for_condition 50 1000 {
  39. [log_file_matches $slave_log "*Timeout connecting to the MASTER*"]
  40. } else {
  41. fail "Replica is not able to detect timeout"
  42. }
  43. }
  44. }
  45. }
  46. start_server {tags {"repl external:skip"}} {
  47. set A [srv 0 client]
  48. set A_host [srv 0 host]
  49. set A_port [srv 0 port]
  50. start_server {} {
  51. set B [srv 0 client]
  52. set B_host [srv 0 host]
  53. set B_port [srv 0 port]
  54. test {Set instance A as slave of B} {
  55. $A slaveof $B_host $B_port
  56. wait_for_condition 50 100 {
  57. [lindex [$A role] 0] eq {slave} &&
  58. [string match {*master_link_status:up*} [$A info replication]]
  59. } else {
  60. fail "Can't turn the instance into a replica"
  61. }
  62. }
  63. test {INCRBYFLOAT replication, should not remove expire} {
  64. r set test 1 EX 100
  65. r incrbyfloat test 0.1
  66. after 1000
  67. assert_equal [$A debug digest] [$B debug digest]
  68. }
  69. test {GETSET replication} {
  70. $A config resetstat
  71. $A config set loglevel debug
  72. $B config set loglevel debug
  73. r set test foo
  74. assert_equal [r getset test bar] foo
  75. wait_for_condition 500 10 {
  76. [$A get test] eq "bar"
  77. } else {
  78. fail "getset wasn't propagated"
  79. }
  80. assert_equal [r set test vaz get] bar
  81. wait_for_condition 500 10 {
  82. [$A get test] eq "vaz"
  83. } else {
  84. fail "set get wasn't propagated"
  85. }
  86. assert_match {*calls=3,*} [cmdrstat set $A]
  87. assert_match {} [cmdrstat getset $A]
  88. }
  89. test {BRPOPLPUSH replication, when blocking against empty list} {
  90. $A config resetstat
  91. set rd [redis_deferring_client]
  92. $rd brpoplpush a b 5
  93. r lpush a foo
  94. wait_for_condition 50 100 {
  95. [$A debug digest] eq [$B debug digest]
  96. } else {
  97. fail "Master and replica have different digest: [$A debug digest] VS [$B debug digest]"
  98. }
  99. assert_match {*calls=1,*} [cmdrstat rpoplpush $A]
  100. assert_match {} [cmdrstat lmove $A]
  101. }
  102. test {BRPOPLPUSH replication, list exists} {
  103. $A config resetstat
  104. set rd [redis_deferring_client]
  105. r lpush c 1
  106. r lpush c 2
  107. r lpush c 3
  108. $rd brpoplpush c d 5
  109. after 1000
  110. assert_equal [$A debug digest] [$B debug digest]
  111. assert_match {*calls=1,*} [cmdrstat rpoplpush $A]
  112. assert_match {} [cmdrstat lmove $A]
  113. }
  114. foreach wherefrom {left right} {
  115. foreach whereto {left right} {
  116. test "BLMOVE ($wherefrom, $whereto) replication, when blocking against empty list" {
  117. $A config resetstat
  118. set rd [redis_deferring_client]
  119. $rd blmove a b $wherefrom $whereto 5
  120. r lpush a foo
  121. wait_for_condition 50 100 {
  122. [$A debug digest] eq [$B debug digest]
  123. } else {
  124. fail "Master and replica have different digest: [$A debug digest] VS [$B debug digest]"
  125. }
  126. assert_match {*calls=1,*} [cmdrstat lmove $A]
  127. assert_match {} [cmdrstat rpoplpush $A]
  128. }
  129. test "BLMOVE ($wherefrom, $whereto) replication, list exists" {
  130. $A config resetstat
  131. set rd [redis_deferring_client]
  132. r lpush c 1
  133. r lpush c 2
  134. r lpush c 3
  135. $rd blmove c d $wherefrom $whereto 5
  136. after 1000
  137. assert_equal [$A debug digest] [$B debug digest]
  138. assert_match {*calls=1,*} [cmdrstat lmove $A]
  139. assert_match {} [cmdrstat rpoplpush $A]
  140. }
  141. }
  142. }
  143. test {BLPOP followed by role change, issue #2473} {
  144. set rd [redis_deferring_client]
  145. $rd blpop foo 0 ; # Block while B is a master
  146. # Turn B into master of A
  147. $A slaveof no one
  148. $B slaveof $A_host $A_port
  149. wait_for_condition 50 100 {
  150. [lindex [$B role] 0] eq {slave} &&
  151. [string match {*master_link_status:up*} [$B info replication]]
  152. } else {
  153. fail "Can't turn the instance into a replica"
  154. }
  155. # Push elements into the "foo" list of the new replica.
  156. # If the client is still attached to the instance, we'll get
  157. # a desync between the two instances.
  158. $A rpush foo a b c
  159. after 100
  160. wait_for_condition 50 100 {
  161. [$A debug digest] eq [$B debug digest] &&
  162. [$A lrange foo 0 -1] eq {a b c} &&
  163. [$B lrange foo 0 -1] eq {a b c}
  164. } else {
  165. fail "Master and replica have different digest: [$A debug digest] VS [$B debug digest]"
  166. }
  167. }
  168. }
  169. }
  170. start_server {tags {"repl external:skip"}} {
  171. r set mykey foo
  172. start_server {} {
  173. test {Second server should have role master at first} {
  174. s role
  175. } {master}
  176. test {SLAVEOF should start with link status "down"} {
  177. r multi
  178. r slaveof [srv -1 host] [srv -1 port]
  179. r info replication
  180. r exec
  181. } {*master_link_status:down*}
  182. test {The role should immediately be changed to "replica"} {
  183. s role
  184. } {slave}
  185. wait_for_sync r
  186. test {Sync should have transferred keys from master} {
  187. r get mykey
  188. } {foo}
  189. test {The link status should be up} {
  190. s master_link_status
  191. } {up}
  192. test {SET on the master should immediately propagate} {
  193. r -1 set mykey bar
  194. wait_for_condition 500 100 {
  195. [r 0 get mykey] eq {bar}
  196. } else {
  197. fail "SET on master did not propagated on replica"
  198. }
  199. }
  200. test {FLUSHALL should replicate} {
  201. r -1 flushall
  202. if {$::valgrind} {after 2000}
  203. list [r -1 dbsize] [r 0 dbsize]
  204. } {0 0}
  205. test {ROLE in master reports master with a slave} {
  206. set res [r -1 role]
  207. lassign $res role offset slaves
  208. assert {$role eq {master}}
  209. assert {$offset > 0}
  210. assert {[llength $slaves] == 1}
  211. lassign [lindex $slaves 0] master_host master_port slave_offset
  212. assert {$slave_offset <= $offset}
  213. }
  214. test {ROLE in slave reports slave in connected state} {
  215. set res [r role]
  216. lassign $res role master_host master_port slave_state slave_offset
  217. assert {$role eq {slave}}
  218. assert {$slave_state eq {connected}}
  219. }
  220. }
  221. }
  222. foreach mdl {no yes} {
  223. foreach sdl {disabled swapdb} {
  224. start_server {tags {"repl external:skip"}} {
  225. set master [srv 0 client]
  226. $master config set repl-diskless-sync $mdl
  227. $master config set repl-diskless-sync-delay 1
  228. set master_host [srv 0 host]
  229. set master_port [srv 0 port]
  230. set slaves {}
  231. start_server {} {
  232. lappend slaves [srv 0 client]
  233. start_server {} {
  234. lappend slaves [srv 0 client]
  235. start_server {} {
  236. lappend slaves [srv 0 client]
  237. test "Connect multiple replicas at the same time (issue #141), master diskless=$mdl, replica diskless=$sdl" {
  238. # start load handles only inside the test, so that the test can be skipped
  239. set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000000]
  240. set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000000]
  241. set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000000]
  242. set load_handle3 [start_write_load $master_host $master_port 8]
  243. set load_handle4 [start_write_load $master_host $master_port 4]
  244. after 5000 ;# wait for some data to accumulate so that we have RDB part for the fork
  245. # Send SLAVEOF commands to slaves
  246. [lindex $slaves 0] config set repl-diskless-load $sdl
  247. [lindex $slaves 1] config set repl-diskless-load $sdl
  248. [lindex $slaves 2] config set repl-diskless-load $sdl
  249. [lindex $slaves 0] slaveof $master_host $master_port
  250. [lindex $slaves 1] slaveof $master_host $master_port
  251. [lindex $slaves 2] slaveof $master_host $master_port
  252. # Wait for all the three slaves to reach the "online"
  253. # state from the POV of the master.
  254. set retry 500
  255. while {$retry} {
  256. set info [r -3 info]
  257. if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {
  258. break
  259. } else {
  260. incr retry -1
  261. after 100
  262. }
  263. }
  264. if {$retry == 0} {
  265. error "assertion:Slaves not correctly synchronized"
  266. }
  267. # Wait that slaves acknowledge they are online so
  268. # we are sure that DBSIZE and DEBUG DIGEST will not
  269. # fail because of timing issues.
  270. wait_for_condition 500 100 {
  271. [lindex [[lindex $slaves 0] role] 3] eq {connected} &&
  272. [lindex [[lindex $slaves 1] role] 3] eq {connected} &&
  273. [lindex [[lindex $slaves 2] role] 3] eq {connected}
  274. } else {
  275. fail "Slaves still not connected after some time"
  276. }
  277. # Stop the write load
  278. stop_bg_complex_data $load_handle0
  279. stop_bg_complex_data $load_handle1
  280. stop_bg_complex_data $load_handle2
  281. stop_write_load $load_handle3
  282. stop_write_load $load_handle4
  283. # Make sure no more commands processed
  284. wait_load_handlers_disconnected
  285. wait_for_ofs_sync $master [lindex $slaves 0]
  286. wait_for_ofs_sync $master [lindex $slaves 1]
  287. wait_for_ofs_sync $master [lindex $slaves 2]
  288. # Check digests
  289. set digest [$master debug digest]
  290. set digest0 [[lindex $slaves 0] debug digest]
  291. set digest1 [[lindex $slaves 1] debug digest]
  292. set digest2 [[lindex $slaves 2] debug digest]
  293. assert {$digest ne 0000000000000000000000000000000000000000}
  294. assert {$digest eq $digest0}
  295. assert {$digest eq $digest1}
  296. assert {$digest eq $digest2}
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. }
  304. start_server {tags {"repl external:skip"}} {
  305. set master [srv 0 client]
  306. set master_host [srv 0 host]
  307. set master_port [srv 0 port]
  308. start_server {} {
  309. test "Master stream is correctly processed while the replica has a script in -BUSY state" {
  310. set load_handle0 [start_write_load $master_host $master_port 3]
  311. set slave [srv 0 client]
  312. $slave config set lua-time-limit 500
  313. $slave slaveof $master_host $master_port
  314. # Wait for the slave to be online
  315. wait_for_condition 500 100 {
  316. [lindex [$slave role] 3] eq {connected}
  317. } else {
  318. fail "Replica still not connected after some time"
  319. }
  320. # Wait some time to make sure the master is sending data
  321. # to the slave.
  322. after 5000
  323. # Stop the ability of the slave to process data by sendig
  324. # a script that will put it in BUSY state.
  325. $slave eval {for i=1,3000000000 do end} 0
  326. # Wait some time again so that more master stream will
  327. # be processed.
  328. after 2000
  329. # Stop the write load
  330. stop_write_load $load_handle0
  331. # number of keys
  332. wait_for_condition 500 100 {
  333. [$master debug digest] eq [$slave debug digest]
  334. } else {
  335. fail "Different datasets between replica and master"
  336. }
  337. }
  338. }
  339. }
  340. test {slave fails full sync and diskless load swapdb recovers it} {
  341. start_server {tags {"repl"}} {
  342. set slave [srv 0 client]
  343. set slave_host [srv 0 host]
  344. set slave_port [srv 0 port]
  345. set slave_log [srv 0 stdout]
  346. start_server {} {
  347. set master [srv 0 client]
  348. set master_host [srv 0 host]
  349. set master_port [srv 0 port]
  350. # Put different data sets on the master and slave
  351. # we need to put large keys on the master since the slave replies to info only once in 2mb
  352. $slave debug populate 2000 slave 10
  353. $master debug populate 800 master 100000
  354. $master config set rdbcompression no
  355. # Set master and slave to use diskless replication
  356. $master config set repl-diskless-sync yes
  357. $master config set repl-diskless-sync-delay 0
  358. $slave config set repl-diskless-load swapdb
  359. # Set master with a slow rdb generation, so that we can easily disconnect it mid sync
  360. # 10ms per key, with 800 keys is 8 seconds
  361. $master config set rdb-key-save-delay 10000
  362. # Start the replication process...
  363. $slave slaveof $master_host $master_port
  364. # wait for the slave to start reading the rdb
  365. wait_for_condition 50 100 {
  366. [s -1 loading] eq 1
  367. } else {
  368. fail "Replica didn't get into loading mode"
  369. }
  370. # make sure that next sync will not start immediately so that we can catch the slave in between syncs
  371. $master config set repl-diskless-sync-delay 5
  372. # for faster server shutdown, make rdb saving fast again (the fork is already uses the slow one)
  373. $master config set rdb-key-save-delay 0
  374. # waiting slave to do flushdb (key count drop)
  375. wait_for_condition 50 100 {
  376. 2000 != [scan [regexp -inline {keys\=([\d]*)} [$slave info keyspace]] keys=%d]
  377. } else {
  378. fail "Replica didn't flush"
  379. }
  380. # make sure we're still loading
  381. assert_equal [s -1 loading] 1
  382. # kill the slave connection on the master
  383. set killed [$master client kill type slave]
  384. # wait for loading to stop (fail)
  385. wait_for_condition 50 100 {
  386. [s -1 loading] eq 0
  387. } else {
  388. fail "Replica didn't disconnect"
  389. }
  390. # make sure the original keys were restored
  391. assert_equal [$slave dbsize] 2000
  392. }
  393. }
  394. } {} {external:skip}
  395. test {diskless loading short read} {
  396. start_server {tags {"repl"}} {
  397. set replica [srv 0 client]
  398. set replica_host [srv 0 host]
  399. set replica_port [srv 0 port]
  400. start_server {} {
  401. set master [srv 0 client]
  402. set master_host [srv 0 host]
  403. set master_port [srv 0 port]
  404. # Set master and replica to use diskless replication
  405. $master config set repl-diskless-sync yes
  406. $master config set rdbcompression no
  407. $replica config set repl-diskless-load swapdb
  408. $master config set hz 500
  409. $replica config set hz 500
  410. $master config set dynamic-hz no
  411. $replica config set dynamic-hz no
  412. # Try to fill the master with all types of data types / encodings
  413. set start [clock clicks -milliseconds]
  414. for {set k 0} {$k < 3} {incr k} {
  415. for {set i 0} {$i < 10} {incr i} {
  416. r set "$k int_$i" [expr {int(rand()*10000)}]
  417. r expire "$k int_$i" [expr {int(rand()*10000)}]
  418. r set "$k string_$i" [string repeat A [expr {int(rand()*1000000)}]]
  419. r hset "$k hash_small" [string repeat A [expr {int(rand()*10)}]] 0[string repeat A [expr {int(rand()*10)}]]
  420. r hset "$k hash_large" [string repeat A [expr {int(rand()*10000)}]] [string repeat A [expr {int(rand()*1000000)}]]
  421. r sadd "$k set_small" [string repeat A [expr {int(rand()*10)}]]
  422. r sadd "$k set_large" [string repeat A [expr {int(rand()*1000000)}]]
  423. r zadd "$k zset_small" [expr {rand()}] [string repeat A [expr {int(rand()*10)}]]
  424. r zadd "$k zset_large" [expr {rand()}] [string repeat A [expr {int(rand()*1000000)}]]
  425. r lpush "$k list_small" [string repeat A [expr {int(rand()*10)}]]
  426. r lpush "$k list_large" [string repeat A [expr {int(rand()*1000000)}]]
  427. for {set j 0} {$j < 10} {incr j} {
  428. r xadd "$k stream" * foo "asdf" bar "1234"
  429. }
  430. r xgroup create "$k stream" "mygroup_$i" 0
  431. r xreadgroup GROUP "mygroup_$i" Alice COUNT 1 STREAMS "$k stream" >
  432. }
  433. }
  434. if {$::verbose} {
  435. set end [clock clicks -milliseconds]
  436. set duration [expr $end - $start]
  437. puts "filling took $duration ms (TODO: use pipeline)"
  438. set start [clock clicks -milliseconds]
  439. }
  440. # Start the replication process...
  441. set loglines [count_log_lines -1]
  442. $master config set repl-diskless-sync-delay 0
  443. $replica replicaof $master_host $master_port
  444. # kill the replication at various points
  445. set attempts 100
  446. if {$::accurate} { set attempts 500 }
  447. for {set i 0} {$i < $attempts} {incr i} {
  448. # wait for the replica to start reading the rdb
  449. # using the log file since the replica only responds to INFO once in 2mb
  450. set res [wait_for_log_messages -1 {"*Loading DB in memory*"} $loglines 2000 1]
  451. set loglines [lindex $res 1]
  452. # add some additional random sleep so that we kill the master on a different place each time
  453. after [expr {int(rand()*50)}]
  454. # kill the replica connection on the master
  455. set killed [$master client kill type replica]
  456. set res [wait_for_log_messages -1 {"*Internal error in RDB*" "*Finished with success*" "*Successful partial resynchronization*"} $loglines 1000 1]
  457. if {$::verbose} { puts $res }
  458. set log_text [lindex $res 0]
  459. set loglines [lindex $res 1]
  460. if {![string match "*Internal error in RDB*" $log_text]} {
  461. # force the replica to try another full sync
  462. $master multi
  463. $master client kill type replica
  464. $master set asdf asdf
  465. # the side effect of resizing the backlog is that it is flushed (16k is the min size)
  466. $master config set repl-backlog-size [expr {16384 + $i}]
  467. $master exec
  468. }
  469. # wait for loading to stop (fail)
  470. wait_for_condition 1000 1 {
  471. [s -1 loading] eq 0
  472. } else {
  473. fail "Replica didn't disconnect"
  474. }
  475. }
  476. if {$::verbose} {
  477. set end [clock clicks -milliseconds]
  478. set duration [expr $end - $start]
  479. puts "test took $duration ms"
  480. }
  481. # enable fast shutdown
  482. $master config set rdb-key-save-delay 0
  483. }
  484. }
  485. } {} {external:skip}
  486. # get current stime and utime metrics for a thread (since it's creation)
  487. proc get_cpu_metrics { statfile } {
  488. if { [ catch {
  489. set fid [ open $statfile r ]
  490. set data [ read $fid 1024 ]
  491. ::close $fid
  492. set data [ split $data ]
  493. ;## number of jiffies it has been scheduled...
  494. set utime [ lindex $data 13 ]
  495. set stime [ lindex $data 14 ]
  496. } err ] } {
  497. error "assertion:can't parse /proc: $err"
  498. }
  499. set mstime [clock milliseconds]
  500. return [ list $mstime $utime $stime ]
  501. }
  502. # compute %utime and %stime of a thread between two measurements
  503. proc compute_cpu_usage {start end} {
  504. set clock_ticks [exec getconf CLK_TCK]
  505. # convert ms time to jiffies and calc delta
  506. set dtime [ expr { ([lindex $end 0] - [lindex $start 0]) * double($clock_ticks) / 1000 } ]
  507. set utime [ expr { [lindex $end 1] - [lindex $start 1] } ]
  508. set stime [ expr { [lindex $end 2] - [lindex $start 2] } ]
  509. set pucpu [ expr { ($utime / $dtime) * 100 } ]
  510. set pscpu [ expr { ($stime / $dtime) * 100 } ]
  511. return [ list $pucpu $pscpu ]
  512. }
  513. # test diskless rdb pipe with multiple replicas, which may drop half way
  514. start_server {tags {"repl external:skip"}} {
  515. set master [srv 0 client]
  516. $master config set repl-diskless-sync yes
  517. $master config set repl-diskless-sync-delay 1
  518. set master_host [srv 0 host]
  519. set master_port [srv 0 port]
  520. set master_pid [srv 0 pid]
  521. # put enough data in the db that the rdb file will be bigger than the socket buffers
  522. # and since we'll have key-load-delay of 100, 20000 keys will take at least 2 seconds
  523. # we also need the replica to process requests during transfer (which it does only once in 2mb)
  524. $master debug populate 20000 test 10000
  525. $master config set rdbcompression no
  526. # If running on Linux, we also measure utime/stime to detect possible I/O handling issues
  527. set os [catch {exec uname}]
  528. set measure_time [expr {$os == "Linux"} ? 1 : 0]
  529. foreach all_drop {no slow fast all timeout} {
  530. test "diskless $all_drop replicas drop during rdb pipe" {
  531. set replicas {}
  532. set replicas_alive {}
  533. # start one replica that will read the rdb fast, and one that will be slow
  534. start_server {} {
  535. lappend replicas [srv 0 client]
  536. lappend replicas_alive [srv 0 client]
  537. start_server {} {
  538. lappend replicas [srv 0 client]
  539. lappend replicas_alive [srv 0 client]
  540. # start replication
  541. # it's enough for just one replica to be slow, and have it's write handler enabled
  542. # so that the whole rdb generation process is bound to that
  543. set loglines [count_log_lines -1]
  544. [lindex $replicas 0] config set repl-diskless-load swapdb
  545. [lindex $replicas 0] config set key-load-delay 100 ;# 20k keys and 100 microseconds sleep means at least 2 seconds
  546. [lindex $replicas 0] replicaof $master_host $master_port
  547. [lindex $replicas 1] replicaof $master_host $master_port
  548. # wait for the replicas to start reading the rdb
  549. # using the log file since the replica only responds to INFO once in 2mb
  550. wait_for_log_messages -1 {"*Loading DB in memory*"} $loglines 800 10
  551. if {$measure_time} {
  552. set master_statfile "/proc/$master_pid/stat"
  553. set master_start_metrics [get_cpu_metrics $master_statfile]
  554. set start_time [clock seconds]
  555. }
  556. # wait a while so that the pipe socket writer will be
  557. # blocked on write (since replica 0 is slow to read from the socket)
  558. after 500
  559. # add some command to be present in the command stream after the rdb.
  560. $master incr $all_drop
  561. # disconnect replicas depending on the current test
  562. set loglines [count_log_lines -2]
  563. if {$all_drop == "all" || $all_drop == "fast"} {
  564. exec kill [srv 0 pid]
  565. set replicas_alive [lreplace $replicas_alive 1 1]
  566. }
  567. if {$all_drop == "all" || $all_drop == "slow"} {
  568. exec kill [srv -1 pid]
  569. set replicas_alive [lreplace $replicas_alive 0 0]
  570. }
  571. if {$all_drop == "timeout"} {
  572. $master config set repl-timeout 2
  573. # we want the slow replica to hang on a key for very long so it'll reach repl-timeout
  574. exec kill -SIGSTOP [srv -1 pid]
  575. after 2000
  576. }
  577. # wait for rdb child to exit
  578. wait_for_condition 500 100 {
  579. [s -2 rdb_bgsave_in_progress] == 0
  580. } else {
  581. fail "rdb child didn't terminate"
  582. }
  583. # make sure we got what we were aiming for, by looking for the message in the log file
  584. if {$all_drop == "all"} {
  585. wait_for_log_messages -2 {"*Diskless rdb transfer, last replica dropped, killing fork child*"} $loglines 1 1
  586. }
  587. if {$all_drop == "no"} {
  588. wait_for_log_messages -2 {"*Diskless rdb transfer, done reading from pipe, 2 replicas still up*"} $loglines 1 1
  589. }
  590. if {$all_drop == "slow" || $all_drop == "fast"} {
  591. wait_for_log_messages -2 {"*Diskless rdb transfer, done reading from pipe, 1 replicas still up*"} $loglines 1 1
  592. }
  593. if {$all_drop == "timeout"} {
  594. wait_for_log_messages -2 {"*Disconnecting timedout replica (full sync)*"} $loglines 1 1
  595. wait_for_log_messages -2 {"*Diskless rdb transfer, done reading from pipe, 1 replicas still up*"} $loglines 1 1
  596. # master disconnected the slow replica, remove from array
  597. set replicas_alive [lreplace $replicas_alive 0 0]
  598. # release it
  599. exec kill -SIGCONT [srv -1 pid]
  600. }
  601. # make sure we don't have a busy loop going thought epoll_wait
  602. if {$measure_time} {
  603. set master_end_metrics [get_cpu_metrics $master_statfile]
  604. set time_elapsed [expr {[clock seconds]-$start_time}]
  605. set master_cpu [compute_cpu_usage $master_start_metrics $master_end_metrics]
  606. set master_utime [lindex $master_cpu 0]
  607. set master_stime [lindex $master_cpu 1]
  608. if {$::verbose} {
  609. puts "elapsed: $time_elapsed"
  610. puts "master utime: $master_utime"
  611. puts "master stime: $master_stime"
  612. }
  613. if {!$::no_latency && ($all_drop == "all" || $all_drop == "slow" || $all_drop == "timeout")} {
  614. assert {$master_utime < 70}
  615. assert {$master_stime < 70}
  616. }
  617. if {!$::no_latency && ($all_drop == "none" || $all_drop == "fast")} {
  618. assert {$master_utime < 15}
  619. assert {$master_stime < 15}
  620. }
  621. }
  622. # verify the data integrity
  623. foreach replica $replicas_alive {
  624. # Wait that replicas acknowledge they are online so
  625. # we are sure that DBSIZE and DEBUG DIGEST will not
  626. # fail because of timing issues.
  627. wait_for_condition 150 100 {
  628. [lindex [$replica role] 3] eq {connected}
  629. } else {
  630. fail "replicas still not connected after some time"
  631. }
  632. # Make sure that replicas and master have same
  633. # number of keys
  634. wait_for_condition 50 100 {
  635. [$master dbsize] == [$replica dbsize]
  636. } else {
  637. fail "Different number of keys between master and replicas after too long time."
  638. }
  639. # Check digests
  640. set digest [$master debug digest]
  641. set digest0 [$replica debug digest]
  642. assert {$digest ne 0000000000000000000000000000000000000000}
  643. assert {$digest eq $digest0}
  644. }
  645. }
  646. }
  647. }
  648. }
  649. }
  650. test "diskless replication child being killed is collected" {
  651. # when diskless master is waiting for the replica to become writable
  652. # it removes the read event from the rdb pipe so if the child gets killed
  653. # the replica will hung. and the master may not collect the pid with waitpid
  654. start_server {tags {"repl"}} {
  655. set master [srv 0 client]
  656. set master_host [srv 0 host]
  657. set master_port [srv 0 port]
  658. set master_pid [srv 0 pid]
  659. $master config set repl-diskless-sync yes
  660. $master config set repl-diskless-sync-delay 0
  661. # put enough data in the db that the rdb file will be bigger than the socket buffers
  662. $master debug populate 20000 test 10000
  663. $master config set rdbcompression no
  664. start_server {} {
  665. set replica [srv 0 client]
  666. set loglines [count_log_lines 0]
  667. $replica config set repl-diskless-load swapdb
  668. $replica config set key-load-delay 1000000
  669. $replica replicaof $master_host $master_port
  670. # wait for the replicas to start reading the rdb
  671. wait_for_log_messages 0 {"*Loading DB in memory*"} $loglines 800 10
  672. # wait to be sure the eplica is hung and the master is blocked on write
  673. after 500
  674. # simulate the OOM killer or anyone else kills the child
  675. set fork_child_pid [get_child_pid -1]
  676. exec kill -9 $fork_child_pid
  677. # wait for the parent to notice the child have exited
  678. wait_for_condition 50 100 {
  679. [s -1 rdb_bgsave_in_progress] == 0
  680. } else {
  681. fail "rdb child didn't terminate"
  682. }
  683. }
  684. }
  685. } {} {external:skip}
  686. test "diskless replication read pipe cleanup" {
  687. # In diskless replication, we create a read pipe for the RDB, between the child and the parent.
  688. # When we close this pipe (fd), the read handler also needs to be removed from the event loop (if it still registered).
  689. # Otherwise, next time we will use the same fd, the registration will be fail (panic), because
  690. # we will use EPOLL_CTL_MOD (the fd still register in the event loop), on fd that already removed from epoll_ctl
  691. start_server {tags {"repl"}} {
  692. set master [srv 0 client]
  693. set master_host [srv 0 host]
  694. set master_port [srv 0 port]
  695. set master_pid [srv 0 pid]
  696. $master config set repl-diskless-sync yes
  697. $master config set repl-diskless-sync-delay 0
  698. # put enough data in the db, and slowdown the save, to keep the parent busy at the read process
  699. $master config set rdb-key-save-delay 100000
  700. $master debug populate 20000 test 10000
  701. $master config set rdbcompression no
  702. start_server {} {
  703. set replica [srv 0 client]
  704. set loglines [count_log_lines 0]
  705. $replica config set repl-diskless-load swapdb
  706. $replica replicaof $master_host $master_port
  707. # wait for the replicas to start reading the rdb
  708. wait_for_log_messages 0 {"*Loading DB in memory*"} $loglines 800 10
  709. set loglines [count_log_lines 0]
  710. # send FLUSHALL so the RDB child will be killed
  711. $master flushall
  712. # wait for another RDB child process to be started
  713. wait_for_log_messages -1 {"*Background RDB transfer started by pid*"} $loglines 800 10
  714. # make sure master is alive
  715. $master ping
  716. }
  717. }
  718. } {} {external:skip}
  719. test {replicaof right after disconnection} {
  720. # this is a rare race condition that was reproduced sporadically by the psync2 unit.
  721. # see details in #7205
  722. start_server {tags {"repl"}} {
  723. set replica1 [srv 0 client]
  724. set replica1_host [srv 0 host]
  725. set replica1_port [srv 0 port]
  726. set replica1_log [srv 0 stdout]
  727. start_server {} {
  728. set replica2 [srv 0 client]
  729. set replica2_host [srv 0 host]
  730. set replica2_port [srv 0 port]
  731. set replica2_log [srv 0 stdout]
  732. start_server {} {
  733. set master [srv 0 client]
  734. set master_host [srv 0 host]
  735. set master_port [srv 0 port]
  736. $replica1 replicaof $master_host $master_port
  737. $replica2 replicaof $master_host $master_port
  738. wait_for_condition 50 100 {
  739. [string match {*master_link_status:up*} [$replica1 info replication]] &&
  740. [string match {*master_link_status:up*} [$replica2 info replication]]
  741. } else {
  742. fail "Can't turn the instance into a replica"
  743. }
  744. set rd [redis_deferring_client -1]
  745. $rd debug sleep 1
  746. after 100
  747. # when replica2 will wake up from the sleep it will find both disconnection
  748. # from it's master and also a replicaof command at the same event loop
  749. $master client kill type replica
  750. $replica2 replicaof $replica1_host $replica1_port
  751. $rd read
  752. wait_for_condition 50 100 {
  753. [string match {*master_link_status:up*} [$replica2 info replication]]
  754. } else {
  755. fail "role change failed."
  756. }
  757. # make sure psync succeeded, and there were no unexpected full syncs.
  758. assert_equal [status $master sync_full] 2
  759. assert_equal [status $replica1 sync_full] 0
  760. assert_equal [status $replica2 sync_full] 0
  761. }
  762. }
  763. }
  764. } {} {external:skip}
  765. test {Kill rdb child process if its dumping RDB is not useful} {
  766. start_server {tags {"repl"}} {
  767. set slave1 [srv 0 client]
  768. start_server {} {
  769. set slave2 [srv 0 client]
  770. start_server {} {
  771. set master [srv 0 client]
  772. set master_host [srv 0 host]
  773. set master_port [srv 0 port]
  774. for {set i 0} {$i < 10} {incr i} {
  775. $master set $i $i
  776. }
  777. # Generating RDB will cost 10s(10 * 1s)
  778. $master config set rdb-key-save-delay 1000000
  779. $master config set repl-diskless-sync no
  780. $master config set save ""
  781. $slave1 slaveof $master_host $master_port
  782. $slave2 slaveof $master_host $master_port
  783. # Wait for starting child
  784. wait_for_condition 50 100 {
  785. ([s 0 rdb_bgsave_in_progress] == 1) &&
  786. ([string match "*wait_bgsave*" [s 0 slave0]]) &&
  787. ([string match "*wait_bgsave*" [s 0 slave1]])
  788. } else {
  789. fail "rdb child didn't start"
  790. }
  791. # Slave1 disconnect with master
  792. $slave1 slaveof no one
  793. # Shouldn't kill child since another slave wait for rdb
  794. after 100
  795. assert {[s 0 rdb_bgsave_in_progress] == 1}
  796. # Slave2 disconnect with master
  797. $slave2 slaveof no one
  798. # Should kill child
  799. wait_for_condition 100 10 {
  800. [s 0 rdb_bgsave_in_progress] eq 0
  801. } else {
  802. fail "can't kill rdb child"
  803. }
  804. # If have save parameters, won't kill child
  805. $master config set save "900 1"
  806. $slave1 slaveof $master_host $master_port
  807. $slave2 slaveof $master_host $master_port
  808. wait_for_condition 50 100 {
  809. ([s 0 rdb_bgsave_in_progress] == 1) &&
  810. ([string match "*wait_bgsave*" [s 0 slave0]]) &&
  811. ([string match "*wait_bgsave*" [s 0 slave1]])
  812. } else {
  813. fail "rdb child didn't start"
  814. }
  815. $slave1 slaveof no one
  816. $slave2 slaveof no one
  817. after 200
  818. assert {[s 0 rdb_bgsave_in_progress] == 1}
  819. catch {$master shutdown nosave}
  820. }
  821. }
  822. }
  823. } {} {external:skip}