Communication
After initialization is complete, Sentinel will actively communicate with master, slave, to obtain their information.
Get Primary Server information
First, Sentinel will establish two connections with master, which are command connections and subscription connections (stored in the CC and PC fields of Sentinelredisinstance, respectively).
The code is as follows |
Copy Code |
void Sentinelhandleredisinstance (Sentinelredisinstance *ri) { Sentinelreconnectinstance (RI); ... } #define Sentinel_hello_channel "__sentinel__:hello" |
The command connection is used for subsequent access to master's information (including slave information), and subscriptions (Sentinel:hello Channels) are used to push messages such as the drop state of master.
When the connection is complete, Sentinel sends a message periodically:
The code is as follows |
Copy Code |
void Sentinelsendperiodiccommands (Sentinelredisinstance *ri) { mstime_t now = Mstime (); mstime_t Info_period, Ping_period; int retval; /* Return ASAP If we have already a PING or INFO already pending, or * In the case, the instance is not properly connected. */ if (Ri->flags & sri_disconnected) return; /* for INFO, PING, PUBLISH this are not critical commands to send we * Also have a limit of sentinel_max_pending_commands. We don ' t * Want to use a lot of memory just because a link isn't not working * Properly (note that anyway there are a redundant protection about this, * That is, the link would be disconnected and reconnected if a long * Timeout condition is detected. */ if (ri->pending_commands >= sentinel_max_pending_commands) return; /* If This is a slave of the A master in o_down condition we start sending * It INFO every second, instead of the usual sentinel_info_period * Period. In the We want to closely monitor slaves in case they * are turned into Masters by another Sentinel, or by the sysadmin. */ INFO command The default send interval is 10s #define SENTINEL_INFO_PERIOD 10000 If you are a slave for a master that has been down, change the 1s if (Ri->flags & Sri_slave) && (Ri->master->flags & (sri_o_down| sri_failover_in_progress))) { Info_period = 1000; } else { Info_period = Sentinel_info_period; } /* We Ping instances every time, received Pong is older than * The configured ' Down-after-milliseconds ' time, but every second * Anyway if ' down-after-milliseconds ' is greater than 1 second. */ PING command default interval 1s #define SENTINEL_PING_PERIOD 1000 Ping_period = ri->down_after_period; if (Ping_period > Sentinel_ping_period) Ping_period = Sentinel_ping_period; if (Ri->flags & Sri_sentinel) = = 0 && (Ri->info_refresh = 0 | | (Now-ri->info_refresh) > Info_period)) { /* Send INFO to Masters and slaves, not sentinels. */ retval = Redisasynccommand (RI->CC, Sentinelinforeplycallback, NULL, "INFO"); if (retval = = REDIS_OK) ri->pending_commands++; else if ((now-ri->last_pong_time) > ping_period) { /* Send PING to all three kinds of instances. */ Sentinelsendping (RI); else if ((now-ri->last_pub_time) > Sentinel_publish_period) { /* PUBLISH Hello messages to the three kinds of instances. */ Sentinelsendhello (RI); } } |
Handling the return of info message:
code is as follows |
copy code |
void Sentinelinforeplycallback (Redisasynccontext *c, void *reply, void *privdata) { Sentinelredisinstance *ri = c->data; redisreply *r; redis_notused (privdata); if (RI) ri->pending_commands-- if (!reply | |!ri) return; r = reply; if (R->type = redis_reply_string) { Sentinelrefreshinstanceinfo (RI,R->STR); } } |
This is for Info,sentinel sent to master:
1. Get Master run_id Records, check master role, update the master list of your own maintenance
2. Copy the fields, get master's slave list, update the slave list that you maintain
Get slave information
Similarly, Sentinel sends the info command to the slave at the same frequency and extracts the following parameters:
* run_id
* Role
* Master's host and port
* The connection status of the master-slave server (master_link_status)
* Slave priority (slave_priority)
* Slave replication offset (slave_repl_offset)
and update the SENTINELREDISINSTANCE structure that you maintain.
Send and receive subscription information
Sentinel sends information to all master and slave through a command connection per second.
The code is as follows |
Copy Code |
int Sentinelsendhello (sentinelredisinstance *ri) { Char Ip[redis_ip_str_len]; Char payload[redis_ip_str_len+1024]; int retval; Char *announce_ip; int announce_port; Sentinelredisinstance *master = (ri->flags & Sri_master)? ri:ri->master; Sentineladdr *master_addr = sentinelgetcurrentmasteraddress (master); if (Ri->flags & sri_disconnected) return redis_err; /* Use the specified announce address if specified, otherwise try to * Obtain our own IP address. */ if (SENTINEL.ANNOUNCE_IP) { Announce_ip = sentinel.announce_ip; } else { if (Anetsockname (ri->cc->c.fd,ip,sizeof (IP), NULL) = =-1) return redis_err; ANNOUNCE_IP = IP; } Announce_port = Sentinel.announce_port? Sentinel.announce_port:server.port; /* Format and send the Hello message. */ snprintf (payload,sizeof (payload), "%s,%d,%s,%llu,"/* Info about this Sentinel. */ "%s,%s,%d,%llu",/* Info about current master. */ Announce_ip, Announce_port, Server.runid, (unsigned long long) Sentinel.current_epoch, /* --- */ Master->name,master_addr->ip,master_addr->port, (unsigned long long) master->config_epoch); retval = Redisasynccommand (RI->CC, Sentinelpublishreplycallback, NULL, "PUBLISH%s%s", Sentinel_hello_channel,payload); if (retval!= REDIS_OK) return redis_err; ri->pending_commands++; return REDIS_OK; } |
Send content includes:
* Sentinel IP (ANNOUNCE_IP)
* Sentinel Port (Announce_port)
* Sentinel Run ID (server.runid)
* Sentinel Configuration era (Sentinel.current_epoch)
* Master Name (master->name)
* Master IP (MASTER_ADDR->IP)
* Master Port (Master_addr->port)
* Master era (Master->config_epoch)
At the same time, all Sentinel connected to this master will receive the message and then respond:
* Update Sentinels Dictionary
* Create a command connection to connect to other Sentinel