溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何解析Redis中的集群主從復(fù)制原理

發(fā)布時(shí)間:2022-01-24 10:34:55 來(lái)源:億速云 閱讀:257 作者:柒染 欄目:關(guān)系型數(shù)據(jù)庫(kù)

這篇文章將為大家詳細(xì)講解有關(guān)如何解析Redis中的集群主從復(fù)制原理,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

本篇文章帶大家深入理解下Redis集群主從復(fù)制原理,希望對(duì)大家有所幫助!

一、首先思考一個(gè)問(wèn)題,為什么redis性能這么高還需要分布式方案?

1、實(shí)現(xiàn)更高性能:高并發(fā)應(yīng)用,單機(jī)性能會(huì)有影響,需要更多redis服務(wù)器分擔(dān)壓力,實(shí)現(xiàn)負(fù)載均衡

2、實(shí)現(xiàn)高可用:如果單機(jī),防止宕機(jī)/硬件故障

3、實(shí)現(xiàn)可擴(kuò)展:?jiǎn)螜C(jī)內(nèi)存和硬件有限制,實(shí)現(xiàn)橫向擴(kuò)展

冗余或者分片存儲(chǔ)實(shí)現(xiàn)如上特性。

二、主從復(fù)制-replication配置

和Kafka,Mysql,Rocketmq一樣,redis支持集群部署,集群節(jié)點(diǎn)有master和slave之分,主節(jié)點(diǎn)是master,從節(jié)點(diǎn)是slave(最新叫副本replica).slave會(huì)通過(guò)復(fù)制機(jī)制,從master同步最新的數(shù)據(jù)。Redis提供了非常方便的命令開(kāi)啟主從復(fù)制?!鞠嚓P(guān)推薦:Redis視頻教程】

如何配置開(kāi)啟主從復(fù)制?

以本機(jī)搭建偽集群為例,6379端口是從節(jié)點(diǎn),6378作為主節(jié)點(diǎn)。

1、從節(jié)點(diǎn)redis.conf配置 replicaof masterip masterport 從節(jié)點(diǎn)啟動(dòng)后,自動(dòng)連接到master節(jié)點(diǎn),開(kāi)始同步數(shù)據(jù).

如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理

源碼說(shuō)明:

//每1s執(zhí)行這個(gè)方法
void replicationCron(void) {
    ...
    //檢查是否需要連接到master 如果是REPL_STATE_CONNECT狀態(tài),必須連接到master
    //#define REPL_STATE_CONNECT 1  Must connect to master 
    if (server.repl_state == REPL_STATE_CONNECT) {
        serverLog(LL_NOTICE,"Connecting to MASTER %s:%d",
            server.masterhost, server.masterport);
        //和master創(chuàng)建連接    
        if (connectWithMaster() == C_OK) {
            serverLog(LL_NOTICE,"MASTER <-> REPLICA sync started");
        }
    }
    
    //發(fā)送ping命令給slave 
    if ((replication_cron_loops % server.repl_ping_slave_period) == 0 &&
        listLength(server.slaves))
    {
        /* Note that we don't send the PING if the clients are paused during
         * a Redis Cluster manual failover: the PING we send will otherwise
         * alter the replication offsets of master and slave, and will no longer
         * match the one stored into 'mf_master_offset' state. */
        int manual_failover_in_progress =
            server.cluster_enabled &&
            server.cluster->mf_end &&
            clientsArePaused();

        if (!manual_failover_in_progress) {
            ping_argv[0] = createStringObject("PING",4);
            replicationFeedSlaves(server.slaves, server.slaveseldb,
                ping_argv, 1);
            decrRefCount(ping_argv[0]);
        }
    }
    
    //發(fā)送換行符到所有slave,告訴slave等待接收rdb文件
    listRewind(server.slaves,&li);
    while((ln = listNext(&li))) {
        client *slave = ln->value;

        int is_presync =
            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START ||
            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END &&
             server.rdb_child_type != RDB_CHILD_TYPE_SOCKET));

        if (is_presync) {
            if (write(slave->fd, "\n", 1) == -1) {
                /* Don't worry about socket errors, it's just a ping. */
            }
        }
    }
    ...
}

3、全量復(fù)制流程-支持無(wú)盤(pán)復(fù)制或者rdb持久化復(fù)制

如何解析Redis中的集群主從復(fù)制原理

當(dāng)slave連接到master后,使用psync(以前是sync命令,它不允許部分重新同步,所以現(xiàn)在改用PSYNC)命令初始化復(fù)制,將主節(jié)點(diǎn)replication id和處理過(guò)最大offset發(fā)送到master。

master節(jié)點(diǎn)擁有如下兩個(gè)屬性,一個(gè)replication id(標(biāo)志實(shí)例),一個(gè)offset(標(biāo)志寫(xiě)入從節(jié)點(diǎn)的stream)

Replication ID, offset

如果主節(jié)點(diǎn)緩沖區(qū)中沒(méi)有足夠的積壓工作,或者如果復(fù)制副本引用的是不再已知的歷史記錄(復(fù)制ID),則會(huì)發(fā)生完全重新同步

源碼說(shuō)明:

    //沒(méi)有在rdb進(jìn)程,沒(méi)有aof重寫(xiě)進(jìn)程
    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
        time_t idle, max_idle = 0;
        int slaves_waiting = 0;
        int mincapa = -1;
        listNode *ln;
        listIter li;

        listRewind(server.slaves,&li);
        while((ln = listNext(&li))) {
            client *slave = ln->value;
            //判斷slave是否是等待bgsave狀態(tài)
            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {
            //多久沒(méi)有發(fā)送心跳或查詢數(shù)據(jù)了 空閑時(shí)間間隔
                idle = server.unixtime - slave->lastinteraction;
                if (idle > max_idle) max_idle = idle;
                slaves_waiting++;
                mincapa = (mincapa == -1) ? slave->slave_capa :
                                            (mincapa & slave->slave_capa);
            }
        }

        if (slaves_waiting &&
            (!server.repl_diskless_sync ||
             max_idle > server.repl_diskless_sync_delay))
        {
            /* Start the BGSAVE. The called function may start a
             * BGSAVE with socket target or disk target depending on the
             * configuration and slaves capabilities. */
             //bgsave rdb生成
            startBgsaveForReplication(mincapa);
        }
    }

復(fù)制過(guò)程中,slave狀態(tài)轉(zhuǎn)換流程。

如何解析Redis中的集群主從復(fù)制原理如何解析Redis中的集群主從復(fù)制原理

四、復(fù)制id理解

每次實(shí)例作為主實(shí)例從頭開(kāi)始重新啟動(dòng),或者將復(fù)制副本提升為主實(shí)例,都會(huì)為此實(shí)例生成一個(gè)新的復(fù)制ID。如果兩個(gè)replica的復(fù)制id相同,則他們可能在不同的時(shí)間,有相同的數(shù)據(jù),對(duì)于保存最新數(shù)據(jù)集的給定歷史記錄(復(fù)制ID),偏移量作為一個(gè)邏輯時(shí)間來(lái)理解。需要通過(guò)Replication ID, offset兩個(gè)數(shù)據(jù)來(lái)判斷。用來(lái)判斷從節(jié)點(diǎn)同步數(shù)據(jù)到哪了。

五、主從復(fù)制常見(jiàn)問(wèn)題

1、slave本身有數(shù)據(jù),會(huì)怎么樣?

slave先刪除自身的數(shù)據(jù),再用rdb文件加載。

2、生成rdb文件的過(guò)程中,客戶端寫(xiě)命令怎么處理?

保存到內(nèi)存緩存中,rdb發(fā)送完成后發(fā)送到slave。

3、Redis復(fù)制如何處理key過(guò)期的?

1、副本不會(huì)使key過(guò)期,而是等待主機(jī)使key過(guò)期。當(dāng)主機(jī)使key過(guò)期(或由于LRU而將其逐出)時(shí),它將合成一個(gè)DEL命令,該命令將傳輸?shù)剿懈北尽?/p>

2、但是,由于主機(jī)驅(qū)動(dòng)的expire,有時(shí)副本可能仍然具有邏輯上已過(guò)期的內(nèi)存密鑰,因?yàn)橹鞣?wù)器無(wú)法及時(shí)提供DEL命令。為了處理這個(gè)問(wèn)題,副本使用它的邏輯時(shí)鐘來(lái)報(bào)告一個(gè)key不存在,只用于不違反數(shù)據(jù)集一致性的讀取操作(因?yàn)閬?lái)自主服務(wù)器的新命令將到達(dá))

3、在Lua腳本執(zhí)行期間,不執(zhí)行密鑰過(guò)期。當(dāng)Lua腳本運(yùn)行時(shí),從概念上講,主節(jié)點(diǎn)中的時(shí)間是凍結(jié)的,因此給定的鍵在腳本運(yùn)行的所有時(shí)間內(nèi)都將存在或不存在。這可以防止key在腳本中間過(guò)期,并且需要key才能以保證在數(shù)據(jù)集中具有相同效果的方式將相同的腳本發(fā)送到副本。

一旦復(fù)制副本升級(jí)為主副本,它將開(kāi)始獨(dú)立地使key過(guò)期,并且不需要舊主副本的任何幫助。

六、主從復(fù)制總結(jié)

1、解決了數(shù)據(jù)備份的問(wèn)題,但是rdb文件大,傳輸大文件,恢復(fù)時(shí)間也長(zhǎng)

2、如果master異常,需要手工將replica選舉為master

3、1主多從,1主1從的情況下,還是存在單點(diǎn)問(wèn)題

4、Redis版本2.8.18后支持無(wú)盤(pán)復(fù)制,性能更高。

七、復(fù)制說(shuō)明

1、默認(rèn)用異步復(fù)制,通過(guò)異步確認(rèn)同步的命令數(shù)量

2、1個(gè)master可以有多個(gè)副本

3、副本也可以有自己的副本,從redis4.0開(kāi)始,副本都會(huì)從主節(jié)點(diǎn)接收完全相同的復(fù)制流

4、復(fù)制既可以用于可擴(kuò)展性,也可以用于只讀查詢的多個(gè)副本

關(guān)于如何解析Redis中的集群主從復(fù)制原理就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI