文章目录
-
- 主从复制概述
- 主从复制使用结构
主从复制概述
关于主从复制的概述半年前写过,篇实践性,有兴趣的小伙伴可以看一下:
【redis】跟我一起动手玩玩redis主从复制和哨兵模式
一般来说,主从、哨兵、集群,三个我都放一起讲的,所以我再放一下关于集群的实践篇吧:
【redis】闲得无聊,来聊聊当下爆火的 redis集群,顺便搭一个玩玩呗
不过源码入手的话实在是庞大,光一块儿就要拆成好几篇来写。
主从复制机制主要有以下作用:
代码语言:javascript复制1、数据冗余
2、读写分离,主写从读
3、故障恢复,主机挂了哨兵马上扶持从机上位
主从复制流程概述:
代码语言:javascript复制1、握手:主从连接成功之后,从节点需要向主节点“自我介绍”
2、同步:连接之后,需要同步数据,使数据达到一致
3、复制:主节点运行阶段将执行的写命令传播给从节点,使用的是异步复制,主节点默认发出即收到,可以提高性能,但是可能在短期内主从数据不一致
同步机制:
代码语言:javascript复制全量同步:简单交涉之后,主节点打包RDB数据发送给从节点,一般用于第一次同步数据。
部分同步:主节点将复制积压区中offset偏移量之后的命令发送给从节点,常用于主从断开重连之后同步数据。
主从复制使用结构
代码语言:javascript复制struct redisServer {
/* Replication (master) */
char replid[CONFIG_RUN_ID_SIZE 1]; // Redis服务器的运行ID,随机字符
char replid2[CONFIG_RUN_ID_SIZE 1]; // 从主服务器中复制出来的ID
long long master_repl_offset; /* My current replication offset */
long long second_replid_offset; /* Accept offsets up to this for replid2. */
int slaveseldb; /* Last SELECTed DB in replication output */
int repl_ping_slave_period; // 发送心跳包的周期
char *repl_backlog; // 复制缓冲区
long long repl_backlog_size; // 复制缓冲区中第一个字节的偏移量
long long repl_backlog_histlen; // 缓冲区中存储的数据真实长度
long long repl_backlog_idx; // 复制缓冲区中最后一个字节的位置
long long repl_backlog_off; /* Replication "master offset" of first
byte in the replication backlog buffer.*/
time_t repl_backlog_time_limit; /* Time without slaves after the backlog
gets released. */
time_t repl_no_slaves_since; /* We have no slaves since that time.
Only valid if server.slaves len is 0. */
int repl_min_slaves_to_write; /* Min number of slaves to write. */
int repl_min_slaves_max_lag; /* Max lag of <count> slaves to write. */
int repl_good_slaves_count; // 当前有效从服务器数量
int repl_diskless_sync; /* Master send RDB to slaves sockets directly. */
int repl_diskless_load; /* Slave parse RDB directly from the socket.
* see REPL_DISKLESS_LOAD_* enum */
int repl_diskless_sync_delay; /* Delay to start a diskless repl BGSAVE. */
/* Replication (slave) */
char *masteruser; /* AUTH with this user and masterauth with master */
char *masterauth; /* AUTH with this password with master */
char *masterhost; /* Hostname of master */
int masterport; /* Port of master */
int repl_timeout; /* Timeout after N seconds of master idle */
client *master; // 连接成功后,主从服务器互为客户端
client *cached_master; /* Cached master to be reused for PSYNC. */
int repl_syncio_timeout; /* Timeout for synchronous I/O calls */
int repl_state; /* Replication status if the instance is a slave */
off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */
connection *repl_transfer_s; /* Slave -> Master SYNC connection */
int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */
char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */
time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */
int repl_serve_stale_data; // 连接断开之后,是否继续处理数据
int repl_slave_ro; // 从机是否被设置为只读
int repl_slave_ignore_maxmemory; /* If true slaves do not evict. */
time_t repl_down_since; /* Unix time at which link with master went down */
int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */
int slave_priority; /* Reported in INFO and used by Sentinel. */
int slave_announce_port; /* Give the master this listening port. */
char *slave_announce_ip; /* Give the master this ip address. */
/* The following two fields is where we store master PSYNC replid/offset
* while the PSYNC is in progress. At the end we'll copy the fields into
* the server->master client structure. */
char master_replid[CONFIG_RUN_ID_SIZE 1]; /* Master PSYNC runid. */
long long master_initial_offset; /* Master PSYNC offset. */
int repl_slave_lazy_flush; /* Lazy FLUSHALL before loading DB? */
/* Replication script cache. */
dict *repl_scriptcache_dict; /* SHA1 all slaves are aware of. */
list *repl_scriptcache_fifo; /* First in, first out LRU eviction. */
unsigned int repl_scriptcache_size; /* Max number of elements. */
/* Synchronous replication. */
list *clients_waiting_acks; /* Clients waiting in WAIT command. */
int get_ack_from_slaves; /* If true we send REPLCONF GETACK. */
};