1. Overview
The overall process is summarized as follows:
1. Initialize
After configuring the master, the slave sends the Psync command to master, whether slave is first or reconnected to master.
If you are reconnecting and the conditions for incremental synchronization are met (as detailed in 3.1), Redis sends the commands in the memory cache queue to slave to complete the incremental sync (Partial resynchronization). Otherwise, full-volume synchronization is performed.
2. Normal sync start
Any writes to Master will be sent to slave via the network in the form of a Redis command. 2. Total sync (full resynchronization) 2.1 process slave send Psync master execute bgsave generate Rdb Snapshot file, and then write new writes command to buffer Master sends the snapshot file to slave and continues to record write command slave receive and save the snapshot slave load the snapshot file into memory slave the command to begin receiving buffers in Master complete synchronization 2.2 instance
Environment:
-Master 127.0.0.1:7779
-Slave 127.0.0.1:9303 process number 10,967 has only one key
Strace-p 10967-s 1024-o Redis.strace.full
Then connect to slave, execute slaveof 127.0.0.1 7779, see from Strace file in the synchronization process, slave side of the action is as follows (only pick the important part)
* * Execute slaveof command from client/read (6, "*3\r\n$7\r\nslaveof\r\n$9\r\n127.0.0.1\r\n$4\r\n7779\r\n", 16384) = 42/* Return to client OK */write (6, "+ok\r\n", 5)/* Connect to master*/Connect (7, {sa_family=af_inet, sin_port=htons (7779), Sin_addr=inet_addr (" 127.0.0.1 ")} =-1 einprogress (Operation now in progress)/* The following judgement Master is Alive/write (7," ping\r\n ", 6) Read (7," + ", 1) = 1 Read (7, "P", 1) = 1 Read (7, "O", 1) = 1 Read ( 7, "N", 1) = 1 Read (7, "G", 1) = 1 Read (7, "\ r", 1) = 1 Read (7, "\ n", 1) = 1/* Sync start, send psync*/write to master (7, "Psync?"). -1\r\n "," =/*master tells Salve to perform full-volume synchronization/Read (7, "+", 1) = 1 Read (7, "F", 1) = 1 Read (7, "U", 1) = 1 Read (7, "L", 1) = 1 Read (7, "L", 1) = 1 Read (7, "R", 1) =1 Read (7, "E", 1) = 1 Read (7, "S", 1) = 1 Read (7, "Y", 1) = 1 Read (7, "N", 1) = 1 Read (7, "C", 1) = 1/* Open Local temporary RDB file * * (" Temp-1472206877.10967.rdb ", o_wronly| O_creat| O_EXCL, 0644) = 8/* Receive the Rdb file from Master */Read (7, "redis0006\376\0\0\4name\4xuan\376\1\r\16hotel_jump_num\33\33\0\0\0\ 30\0\0\0\4\0\0\320\325\2\220\6\6\365\2\320\334\230 (\7\6\370\377\377\336\260\222\330\261\317\371\345 ", 77) = 77/* Writes the received RDB to the temporary rdb*/write (8, "redis0006\376\0\0\4name\4xuan\376\1\r\16hotel_jump_num\33\33\0\0\0\30\0\0\0\4\0\0\320 \325\2\220\6\6\365\2\320\334\230 (\7\6\370\377\377\336\260\222\330\261\317\371\345 ", 77) = 77/* Temporary RDB File rename/rename ( "Temp-1472206877.10967.rdb", "dump.rdb") = 0/* Open Local RDB file * * ("Dump.rdb", o_rdonly) = 9/* Load data from RDB file to slave*/read (9, "R Edis0006\376\0\0\4name\4xuan\376\1\r\16hotel_jump_num\33\33\0\0\0\30\0\0\0\4\0\0\320\325\2\220\6\6\365\2\320\ 334\230 (\7\6\370\377\377\336\260\222\330\261\317\371\345 ", 4096) =/*sync successfully completed, Log/open ("/tmp/redis.log ", o_wronly| O_creat| O_append, 0666) = 8 Fstat (8, {st_mode=s_ifreg|0644, st_size=7627, ...}) = 0 Write (8, "[10967]" Aug 18:21:17.450 * MASTER <-> SLAVE sync:finished with success\n ", 75) = 75
The entire process, as described in 2.1, is just because we did not operate on master during the synchronization process, so strace did not reflect the 6th step in 2.1.
Slave's redis.log also reflects the above process.
[10967] Aug 18:21:17.250 * SLAVE of 127.0.0.1:7779 enabled (user request)
[10967] Aug 18:21:17.410 * connecting To master 127.0.0.1:7779
[10967] Aug 18:21:17.413 * MASTER <-> SLAVE sync started
[10967] Aug 18:21:17 415 * Non blocking Connect for SYNC fired the event.
[10967] Aug 18:21:17.418 * Master replied to PING, replication can continue ...
[10967] Aug 18:21:17.421 * Partial resynchronization not possible (no cached Master)
[10967] Aug 18:21:17.432 * Full resync from master:1d13fbd06f644eeb4b50d65f11e65bffd9e596f6:43774
[10967] Aug 18:21:17.444 * Master <-& Gt SLAVE sync:receiving bytes from master
[10967] Aug 18:21:17.446 * Master <-> SLAVE sync:flushing old dat A
[10967] Aug 18:21:17.447 * MASTER <-> SLAVE sync:loading DB in memory
[10967] Aug 18:21:17.450 * MA Ster <-> SLAVE sync:finished with success
3. Incremental sync (partial resynchronization)
3.1 Conditions of the incremental synchronization
Several important concepts:
-Memory Cache Queue (In-memory backlog): Used to record writes received by Master when a connection is disconnected
-Replication offset (replication offset): Master, Slave has an offset that records the location of the current synchronization record
-Master server ID (Master run ID): Master Unique identifier, 1D13FBD06F644EEB4B50D65F11E65BFFD9E596F6 in the redis.log of 2.2, is a master server ID.
After the current network connection is disconnected, slave will attempt to reconnect master. When the following conditions are met, incremental synchronization occurs after the connection is repeated:
1. The master server ID for the slave record is the same as the master server ID that is currently being connected
2. Slave's replication offset is higher than Master's offset. Like slave is 1000, master is 1100.
3. The data specified by the replication offset for slave is still stored in the memory cache queue of the primary server 3.2 synchronization process
After you confirm that an incremental synchronization is performed, Redis sends the commands in the memory cache queue over the network to slave to complete the incremental Sync 3.3 instance
Environment:
-Master 10.136.30.144:7779
-Slave 10.136.31.213 9303 has a key "H"
First we strace the slave process, and then, in order to simulate the disconnection of the network, we added iptables rules to the master machine and threw away all the packets destined for slave.
/sbin/iptables-a output-d 10.136.31.213-j DROP
Then, delete key h on master
Del h
Finally, we remove the iptables rule, and simulate the situation of network recovery.
/sbin/iptables-f
Let's take a look at slave's log first.
[25667] Aug 15:29:33.241 # Connection with Master lost.
[25667] Aug 15:29:33.241 * Caching the disconnected master state. [25667] Aug 15:29:33.241 * connecting to Master 10.136.30.144:7779 [25667] Aug 15:29:33.241 * MASTER <-> SLAVE Sync started [25667] Aug 15:29:54.240 # Error condition on sockets for sync:connection timed out [25667] Aug 15:29: 54.262 * Connecting to MASTER 10.136.30.144:7779 [25667] Aug 15:29:54.263 * MASTER <-> SLAVE sync started [25667] Num Aug 15:30:15.270 # Error condition on socket for sync:connection timed out [25667] Aug 15:30:15.726 * Connecting T o MASTER 10.136.30.144:7779 [25667] Aug 15:30:15.726 * Master <-> SLAVE sync started [25667] Aug 15:30:36.728 # Error condition on socket for sync:connection timed out [25667]-Aug 15:30:37.272 * Connecting to MASTER 10.136.30.14 4:7779 [25667] Aug 15:30:37.279 * MASTER <-> SLAVE sync started [25667] Aug 15:30:37.282 * Non blocking Connec T for SYNC fired THe event.
[25667] Aug 15:30:37.289 * Master replied to PING, replication can continue ... [25667] Aug 15:30:37.293 * Trying a partial resynchronization (Request 1d13fbd06f644eeb4b50d65f11e65bffd9e596f6:29265
).
[25667] Aug 15:30:37.300 * Successful partial resynchronization with Master. [25667] Aug 15:30:37.302 * MASTER <-> SLAVE Sync:master accepted a Partial resynchronization.
Slave found that after the master was disconnected, he tried to reconnect master until the connection succeeded, attempting an incremental sync (partial resynchronization) and finally completing an incremental synchronization.
The results of Starce also reflect the above process, summarized as follows:
/* Reconnect master*/Connect (6, {sa_family=af_inet, sin_port=htons (7779), sin_addr=inet_addr ("10.136.30.144")}, 16) =-1 Einprogress (Operation now in progress)/* The following judgement Master is Alive/write (6, "ping\r\n", 6) Read (6, "+", 1) = 1 Read (6, "P", 1) = 1 Read (6, "O", 1) = 1 Read (6, "N", 1) = 1 Read (6, "G", 1) = 1 Read (6, "\ r", 1) = 1 Read (6, "\ n", 1) = 1/*slave tries incremental sync, master says yes/write (6, "Psync 1d13fbd06f644eeb4b50d65f11" ...,) = Read (6, "+", 1 = 1 Read (6, "C", 1) = 1 Read (6, "O", 1) = 1 RE AD (6, "N", 1) = 1 Read (6, "T", 1) = 1 Read (6, "I", 1) = 1 Read (6, "N", 1) = 1 Read (6, "U", 1) = 1 Read (6, "E", 1) = 1 Read (6, "\ r"), 1 = 1 Read (6, "\ n", 1) = 1/* Read the increment command during disconnection: Del h*/read (6, "*1\r\n$4\r\npin G\r\n*2\r\n$3\r\ndel\r\n$1\r\nh "..., 16384) = 188
4. NotesThis article mainly describes the reids2.8 and above version of the synchronization process, the version before 2.8 will be slightly different. Reference http://redis.io/topics/replication