搜尋
首頁資料庫Redis淺析Redis中的集群主從複製原理

這篇文章帶大家深入理解下Redis集群主從複製原理,希望對大家有幫助!

淺析Redis中的集群主從複製原理

一、先思考一個問題,為什麼redis效能這麼高還需要分散式方案?

1、實現更高效能:高並發應用,單機效能會有影響,需要更多redis伺服器分擔壓力,實現負載平衡

2、實現高可用:如果單機,防止宕機/硬​​體故障

3、實現可擴展:單機記憶體和硬體有限制,實現橫向擴展

#冗餘或分片存儲實現如上特性。

二、主從複製-replication配置

和Kafka,Mysql,Rocketmq一樣,redis支援叢集部署,叢集節點有master和slave之分,主節點是master,從節點是slave(最新叫副本replica).slave會透過複製機制,從master同步最新的資料。 Redis提供了一個非常方便的命令開啟主從複製。 【相關建議:Redis影片教學

如何設定開啟主從複製?

以本機搭建偽集群為例,6379埠是從節點,6378作為主節點。

1、從節點redis.conf配置replicaof masterip masterport 從節點啟動後,自動連線到master節點,開始同步資料.

淺析Redis中的集群主從複製原理

如果換了新的master節點,這個配置會被重寫。

2、或在redis-server程式啟動時候指定

./redis-server --replicaof masterip masterport

3、或登入客戶端,執行下列指令

slaveof masterip masterport

注意這種方式是執行過程中修改,可以實現故障轉移

注意: 一個從節點也可以是其他節點的主節點,形成級聯複製的關係。但是其他節點也是從頂層主節點同步資料。

配置好叢集後,透過info replication查看叢集狀態

淺析Redis中的集群主從複製原理

#透過role指令,可以查看節點在叢集中的角色資訊

淺析Redis中的集群主從複製原理

注意從節點是唯讀的。寫命令會報錯。

淺析Redis中的集群主從複製原理

slave如何退出叢集?可以執行下列指令: 

slaveof no one

三、主從複製的流程

1、首先是副本-replica加入叢集 

淺析Redis中的集群主從複製原理

#2、與master建立連接,透過計時器定時檢查是否要從主節點同步數據

淺析Redis中的集群主從複製原理

原始碼說明:

//每1s执行这个方法
void replicationCron(void) {
    ...
    //检查是否需要连接到master 如果是REPL_STATE_CONNECT状态,必须连接到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创建连接    
        if (connectWithMaster() == C_OK) {
            serverLog(LL_NOTICE,"MASTER  REPLICA sync started");
        }
    }
    
    //发送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]);
        }
    }
    
    //发送换行符到所有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、全量複製流程-支援無磁碟複製或rdb持久化複製 

淺析Redis中的集群主從複製原理

#當slave連接到master後,使用psync(以前是sync命令,它不允許部分重新同步,所以現在改用PSYNC)命令初始化複製,將主節點replication id和處理過最大offset發送到master。

master節點擁有以下兩個屬性,一個replication id(標誌實例),一個offset(標誌寫入從節點的stream) 

Replication ID, offset

如果主節點緩衝區中沒有足夠的積壓工作,或者如果複製副本引用的是不再已知的歷史記錄(複製ID),則會發生完全重新同步 

原始碼說明:

    //没有在rdb进程,没有aof重写进程
    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状态
            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {
            //多久没有发送心跳或查询数据了 空闲时间间隔
                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);
        }
    }

複製過程中,slave狀態轉換流程。

淺析Redis中的集群主從複製原理

4、命令傳播階段,執行完全量同步後,主從會進行指令傳播實作資料一致。

淺析Redis中的集群主從複製原理

四、複製id理解

#每次實例以主實例從頭開始重新啟動,或將複製副本提升為主實例,都會為此實例產生一個新的複製ID。如果兩個replica的複製id相同,則他們可能在不同的時間,有相同的數據,對於保存最新數據集的給定歷史記錄(複製ID),偏移量作為一個邏輯時間來理解。需要透過Replication ID, offset兩個資料來判斷。用來判斷從節點同步資料到哪了。

五、主從複製常見問題

1、slave本身有數據,會怎麼樣?

slave先刪除自身的數據,再用rdb檔案載入。

2、產生rdb檔案的過程中,客戶端寫指令怎麼處理?

儲存到記憶體快取中,rdb發送完成後傳送到slave。 

3、Redis複製如何處理key過期的? 

1、副本不會使key過期,而是等待主機使key過期。當主機使key過期(或由於LRU而將其逐出)時,它將合成一個DEL命令,該命令將傳輸到所有副本。

2、但是,由於主機驅動的expire,有時副本可能仍然具有邏輯上已過期的記憶體金鑰,因為主伺服器無法及時提供DEL命令。為了處理這個問題,副本使用它的邏輯時鐘來報告一個key不存在,只用於不違反資料集一致性的讀取操作(因為來自主伺服器的新命令將到達)

3、在Lua腳本執行期間,不執行金鑰過期。當Lua腳本運行時,從概念上講,主節點中的時間是凍結的,因此給定的鍵在腳本運行的所有時間內都將存在或不存在。這可以防止key在腳本中間過期,並且需要key才能以保證在資料集中具有相同效果的方式將相同的腳本傳送到副本。

一旦複製副本升級為主副本,它將開始獨立地使key過期,並且不需要舊主副本的任何幫助。

六、主從複製總結

1、解決了資料備份的問題,但是rdb檔案大,傳輸大文件,恢復時間也長

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

3、1主多從,1主1從的情況下,還是存在單點問題 

4、Redis版本2.8.18後支援無碟複製,效能更高。

七、複製說明

1、預設用非同步複製,透過非同步確認同步的指令數

2、1個master可以有多個副本

3、副本也可以有自己的副本,從redis4.0開始,副本都會從主節點接收完全相同的複製流

4、複製既可以用於可擴展性,也可以用於只讀查詢的多個副本

更多程式相關知識,請造訪:程式設計入門! !

以上是淺析Redis中的集群主從複製原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
es和redis区别es和redis区别Jul 06, 2019 pm 01:45 PM

Redis是现在最热门的key-value数据库,Redis的最大特点是key-value存储所带来的简单和高性能;相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,ES的特点是搜索,ES是围绕搜索设计的。

一起来聊聊Redis有什么优势和特点一起来聊聊Redis有什么优势和特点May 16, 2022 pm 06:04 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于redis的一些优势和特点,Redis 是一个开源的使用ANSI C语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式存储数据库,下面一起来看一下,希望对大家有帮助。

实例详解Redis Cluster集群收缩主从节点实例详解Redis Cluster集群收缩主从节点Apr 21, 2022 pm 06:23 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis Cluster集群收缩主从节点的相关问题,包括了Cluster集群收缩概念、将6390主节点从集群中收缩、验证数据迁移过程是否导致数据异常等,希望对大家有帮助。

Redis实现排行榜及相同积分按时间排序功能的实现Redis实现排行榜及相同积分按时间排序功能的实现Aug 22, 2022 pm 05:51 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,希望对大家有帮助。

详细解析Redis中命令的原子性详细解析Redis中命令的原子性Jun 01, 2022 am 11:58 AM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于原子操作中命令原子性的相关问题,包括了处理并发的方案、编程模型、多IO线程以及单命令的相关内容,下面一起看一下,希望对大家有帮助。

实例详解Redis实现排行榜及相同积分按时间排序功能的实现实例详解Redis实现排行榜及相同积分按时间排序功能的实现Aug 26, 2022 pm 02:09 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,下面一起来看一下,希望对大家有帮助。

一文搞懂redis的bitmap一文搞懂redis的bitmapApr 27, 2022 pm 07:48 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了bitmap问题,Redis 为我们提供了位图这一数据结构,位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已,希望对大家有帮助。

redis error什么意思redis error什么意思Jun 17, 2019 am 11:07 AM

redis error就是redis数据库和其组合使用的部件出现错误,这个出现的错误有很多种,例如Redis被配置为保存数据库快照,但它不能持久化到硬盘,用来修改集合数据的命令不能用。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。