1. <dd id="erndk"></dd>
                1. 為什么Redis主從模式能保持數據一致

                  互聯網 2022/5/2 19:13:19

                  為什么Redis主從模式能保持數據一致。想要知道答案,我們得深入分析Redis實例之間如何進行數據同步。 概述 在具體分析今天的問題之前,我們需要了解 Redis 具有高可靠性,又是什么意思呢?其實,這里有兩層含義:一是數據盡量少丟失,二是服務盡量少中斷。AOF 和 RDB 保證…

                  為什么Redis主從模式能保持數據一致。想要知道答案,我們得深入分析Redis實例之間如何進行數據同步。

                  概述

                  在具體分析今天的問題之前,我們需要了解 Redis 具有高可靠性,又是什么意思呢?其實,這里有兩層含義:一是數據盡量少丟失,二是服務盡量少中斷。AOF 和 RDB 保證了前者,而對于后者,Redis 的做法就是增加副本冗余量,將一份數據同時保存在多個實例上。即使有一個實例出現了故障,需要過一段時間才能恢復,其他實例也可以對外提供服務,不會影響業務使用。多實例保存同一份數據,聽起來好像很不錯,但是,我們必須要考慮一個問題:這么多副本,它們之間的數據如何保持一致呢?數據讀寫操作可以發給所有的實例嗎?實際上,Redis 提供了主從庫模式,以保證數據副本的一致,主從庫之間采用的是讀寫分離的方式。

                  1)讀操作:主庫、從庫都可以接收;

                  2)寫操作:首先到主庫執行,然后,主庫將寫操作同步給從庫。

                  到了這里我們發現幾個問題:

                  1)主從庫為什么要采用讀寫分離的方式;

                  2)主庫如何把數據同步給從庫;

                  3)主從庫之前網絡斷了怎么辦;

                  不過既然Redis具有高可用性,說明這些問題都已經有了答案。

                  設計

                  主從庫為什么要采用讀寫分離的方式

                  你可以設想一下,如果不管是主庫還是從庫,都能接收客戶端的寫操作,那么,一個直接的問題就是:如果客戶端對同一個數據(例如 k1)前后修改了三次,每一次的修改請求都發送到不同的實例上,在不同的實例上執行,那么,這個數據在這三個實例上的副本就不一致了(分別是 v1、v2 和 v3)。在讀取這個數據的時候,就可能讀取到舊的值。

                  如果我們非要保持這個數據在三個實例上一致,就要涉及到加鎖、實例間協商是否完成修改等一系列操作,但這會帶來巨額的開銷,當然是不太能接受的。

                   

                  主庫如何把數據同步給從庫

                  當我們啟動多個 Redis 實例的時候,它們相互之間就可以通過 replicaof(Redis 5.0 之前使用 slaveof)命令形成主庫和從庫的關系,之后會按照三個階段完成數據的第一次同步。

                  數據同步

                  第一階段

                  建立連接,協商同步,psync(runId=?,offest=-1),此時主庫會調用FULLRESYNC進行同步。

                  第二階段

                  主庫執行 bgsave 命令,生成 RDB 快照文件,接著將文件發給從庫。從庫接收到 RDB 文件后,會先清空當前數據庫,然后加載 RDB 文件。這是因為從庫在通過 replicaof 命令開始和主庫同步前,可能保存了其他數據。為了避免之前數據的影響,從庫需要先把當前數據庫清空。

                  可能會有人質疑,主庫生成RDB快照文件,不會阻塞主庫的讀寫操作嗎?會不會有額外的性能開銷?那這些問題我們今天就不展開討論了,感興趣的同學可以讀下源碼。

                   

                  rdbSaveBackground就是用來處理在后臺將數據保存到磁盤上的函數:

                   

                  int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { pid_t childpid;
                  if (hasActiveChildProcess()) return C_ERR; ...
                  if ((childpid = redisFork()) == 0) { int retval;
                  /* Child */ redisSetProcTitle("redis-rdb-bgsave"); retval = rdbSave(filename,rsi); if (retval == C_OK) { sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB"); } exitFromChild((retval == C_OK) ? 0 : 1); } else { /* Parent */ ... } ...}

                   

                  第三階段

                  增量復制

                  repl_backlog_buffer

                  最后,也就是第三個階段,主庫會把第二階段執行過程中新收到的寫命令,再發送給從庫。具體的操作是,當主庫完成 RDB 文件發送后,就會把此時 replication buffer 中的修改操作發給從庫,從庫再重新執行這些操作。這樣一來,主從庫就實現同步了。

                   

                  主從庫如果斷開連接了,下次建立連接時會通過repl_backlog_buffer環形緩沖區進行增量復制,psync(runId=1,offest=100),offest=100用于標記從庫在repl_backlog_buffer中的位置。

                   

                  總結

                  為什么Redis主從模式能保持數據一致?

                  • 采用讀寫分離,避免加鎖、實例間協商是否完成修改等操作,減少不必要的性能損耗;
                  • 主從實例間通過RDB快照進行數據同步,同步期間主庫的寫操作額外記錄一份到replication buffer中,同步完成時,發送給從庫,從庫再重新執行這些操作。
                  • 后續的數據同步通過repl_backlog_buffrt來標記主從實例環形緩沖區中的位置,從庫執行這些操作。
                  ?    
                  隨時隨地學軟件編程-關注百度小程序和微信小程序
                  關于找一找教程網

                  本站文章僅代表作者觀點,不代表本站立場,所有文章非營利性免費分享。
                  本站提供了軟件編程、網站開發技術、服務器運維、人工智能等等IT技術文章,希望廣大程序員努力學習,讓我們用科技改變世界。
                  [為什么Redis主從模式能保持數據一致]http://www.yachtsalesaustralia.com/tech/detail-318767.html

                  贊(0)
                  關注微信小程序
                  程序員編程王-隨時隨地學編程

                  掃描二維碼或查找【程序員編程王】

                  可以隨時隨地學編程啦!

                  技術文章導航 更多>
                  国产在线拍揄自揄视频菠萝

                        1. <dd id="erndk"></dd>