replication.tcl 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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"}} {
  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 "Slave 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 "Slave is not able to detect timeout"
  42. }
  43. }
  44. }
  45. }
  46. start_server {tags {"repl"}} {
  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 slave"
  61. }
  62. }
  63. test {BRPOPLPUSH replication, when blocking against empty list} {
  64. set rd [redis_deferring_client]
  65. $rd brpoplpush a b 5
  66. r lpush a foo
  67. wait_for_condition 50 100 {
  68. [$A debug digest] eq [$B debug digest]
  69. } else {
  70. fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
  71. }
  72. }
  73. test {BRPOPLPUSH replication, list exists} {
  74. set rd [redis_deferring_client]
  75. r lpush c 1
  76. r lpush c 2
  77. r lpush c 3
  78. $rd brpoplpush c d 5
  79. after 1000
  80. assert_equal [$A debug digest] [$B debug digest]
  81. }
  82. test {BLPOP followed by role change, issue #2473} {
  83. set rd [redis_deferring_client]
  84. $rd blpop foo 0 ; # Block while B is a master
  85. # Turn B into master of A
  86. $A slaveof no one
  87. $B slaveof $A_host $A_port
  88. wait_for_condition 50 100 {
  89. [lindex [$B role] 0] eq {slave} &&
  90. [string match {*master_link_status:up*} [$B info replication]]
  91. } else {
  92. fail "Can't turn the instance into a slave"
  93. }
  94. # Push elements into the "foo" list of the new slave.
  95. # If the client is still attached to the instance, we'll get
  96. # a desync between the two instances.
  97. $A rpush foo a b c
  98. after 100
  99. wait_for_condition 50 100 {
  100. [$A debug digest] eq [$B debug digest] &&
  101. [$A lrange foo 0 -1] eq {a b c} &&
  102. [$B lrange foo 0 -1] eq {a b c}
  103. } else {
  104. fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
  105. }
  106. }
  107. }
  108. }
  109. start_server {tags {"repl"}} {
  110. r set mykey foo
  111. start_server {} {
  112. test {Second server should have role master at first} {
  113. s role
  114. } {master}
  115. test {SLAVEOF should start with link status "down"} {
  116. r slaveof [srv -1 host] [srv -1 port]
  117. s master_link_status
  118. } {down}
  119. test {The role should immediately be changed to "slave"} {
  120. s role
  121. } {slave}
  122. wait_for_sync r
  123. test {Sync should have transferred keys from master} {
  124. r get mykey
  125. } {foo}
  126. test {The link status should be up} {
  127. s master_link_status
  128. } {up}
  129. test {SET on the master should immediately propagate} {
  130. r -1 set mykey bar
  131. wait_for_condition 500 100 {
  132. [r 0 get mykey] eq {bar}
  133. } else {
  134. fail "SET on master did not propagated on slave"
  135. }
  136. }
  137. test {FLUSHALL should replicate} {
  138. r -1 flushall
  139. if {$::valgrind} {after 2000}
  140. list [r -1 dbsize] [r 0 dbsize]
  141. } {0 0}
  142. test {ROLE in master reports master with a slave} {
  143. set res [r -1 role]
  144. lassign $res role offset slaves
  145. assert {$role eq {master}}
  146. assert {$offset > 0}
  147. assert {[llength $slaves] == 1}
  148. lassign [lindex $slaves 0] master_host master_port slave_offset
  149. assert {$slave_offset <= $offset}
  150. }
  151. test {ROLE in slave reports slave in connected state} {
  152. set res [r role]
  153. lassign $res role master_host master_port slave_state slave_offset
  154. assert {$role eq {slave}}
  155. assert {$slave_state eq {connected}}
  156. }
  157. }
  158. }
  159. foreach dl {no yes} {
  160. start_server {tags {"repl"}} {
  161. set master [srv 0 client]
  162. $master config set repl-diskless-sync $dl
  163. set master_host [srv 0 host]
  164. set master_port [srv 0 port]
  165. set slaves {}
  166. set load_handle0 [start_write_load $master_host $master_port 3]
  167. set load_handle1 [start_write_load $master_host $master_port 5]
  168. set load_handle2 [start_write_load $master_host $master_port 20]
  169. set load_handle3 [start_write_load $master_host $master_port 8]
  170. set load_handle4 [start_write_load $master_host $master_port 4]
  171. start_server {} {
  172. lappend slaves [srv 0 client]
  173. start_server {} {
  174. lappend slaves [srv 0 client]
  175. start_server {} {
  176. lappend slaves [srv 0 client]
  177. test "Connect multiple slaves at the same time (issue #141), diskless=$dl" {
  178. # Send SLAVEOF commands to slaves
  179. [lindex $slaves 0] slaveof $master_host $master_port
  180. [lindex $slaves 1] slaveof $master_host $master_port
  181. [lindex $slaves 2] slaveof $master_host $master_port
  182. # Wait for all the three slaves to reach the "online"
  183. # state from the POV of the master.
  184. set retry 500
  185. while {$retry} {
  186. set info [r -3 info]
  187. if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {
  188. break
  189. } else {
  190. incr retry -1
  191. after 100
  192. }
  193. }
  194. if {$retry == 0} {
  195. error "assertion:Slaves not correctly synchronized"
  196. }
  197. # Wait that slaves acknowledge they are online so
  198. # we are sure that DBSIZE and DEBUG DIGEST will not
  199. # fail because of timing issues.
  200. wait_for_condition 500 100 {
  201. [lindex [[lindex $slaves 0] role] 3] eq {connected} &&
  202. [lindex [[lindex $slaves 1] role] 3] eq {connected} &&
  203. [lindex [[lindex $slaves 2] role] 3] eq {connected}
  204. } else {
  205. fail "Slaves still not connected after some time"
  206. }
  207. # Stop the write load
  208. stop_write_load $load_handle0
  209. stop_write_load $load_handle1
  210. stop_write_load $load_handle2
  211. stop_write_load $load_handle3
  212. stop_write_load $load_handle4
  213. # Make sure that slaves and master have same
  214. # number of keys
  215. wait_for_condition 500 100 {
  216. [$master dbsize] == [[lindex $slaves 0] dbsize] &&
  217. [$master dbsize] == [[lindex $slaves 1] dbsize] &&
  218. [$master dbsize] == [[lindex $slaves 2] dbsize]
  219. } else {
  220. fail "Different number of keys between masted and slave after too long time."
  221. }
  222. # Check digests
  223. set digest [$master debug digest]
  224. set digest0 [[lindex $slaves 0] debug digest]
  225. set digest1 [[lindex $slaves 1] debug digest]
  226. set digest2 [[lindex $slaves 2] debug digest]
  227. assert {$digest ne 0000000000000000000000000000000000000000}
  228. assert {$digest eq $digest0}
  229. assert {$digest eq $digest1}
  230. assert {$digest eq $digest2}
  231. }
  232. }
  233. }
  234. }
  235. }
  236. }