redis源码学习从源码角度看主从复制:前期提要

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis源码学习从源码角度看主从复制:前期提要相关的知识,希望对你有一定的参考价值。

主从复制概述

关于主从复制的概述半年前写过,篇实践性,有兴趣的小伙伴可以看一下:
【redis】跟我一起动手玩玩redis主从复制和哨兵模式

一般来说,主从、哨兵、集群,三个我都放一起讲的,所以我再放一下关于集群的实践篇吧:
【redis】闲得无聊,来聊聊当下爆火的 redis集群,顺便搭一个玩玩呗

不过源码入手的话实在是庞大,光一块儿就要拆成好几篇来写。

主从复制机制主要有以下作用:

1、数据冗余
2、读写分离,主写从读
3、故障恢复,主机挂了哨兵马上扶持从机上位

主从复制流程概述:

1、握手:主从连接成功之后,从节点需要向主节点“自我介绍”
2、同步:连接之后,需要同步数据,使数据达到一致
3、复制:主节点运行阶段将执行的写命令传播给从节点,使用的是异步复制,主节点默认发出即收到,可以提高性能,但是可能在短期内主从数据不一致

同步机制:

全量同步:简单交涉之后,主节点打包RDB数据发送给从节点,一般用于第一次同步数据。
部分同步:主节点将复制积压区中offset偏移量之后的命令发送给从节点,常用于主从断开重连之后同步数据。

主从复制使用结构

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. */
;

以上是关于redis源码学习从源码角度看主从复制:前期提要的主要内容,如果未能解决你的问题,请参考以下文章

redis源码学习从源码角度看主从复制:全量同步 && 部分同步

redis源码阅读-主从复制增量复制细节

redis源码阅读-主从复制增量复制细节

redis源码阅读-主从复制增量复制细节

RocketMQ源码-主从同步复制和异步复制

从源码和内核角度分析redis和nginx以及java NIO可以支持多大的并发