溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis主從技術(shù)的示例分析

發(fā)布時間:2022-02-19 14:09:06 來源:億速云 閱讀:141 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“Redis主從技術(shù)的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“Redis主從技術(shù)的示例分析”這篇文章吧。

Redis復制

在生產(chǎn)環(huán)境中,Redis通過持久化功能(RDB和AOF技術(shù))保證了即使在服務器重啟的情況下也不會損失(或少量損失)數(shù)據(jù)。但是由于數(shù)據(jù)是存儲在一臺服務器上的,如果這臺服務器出現(xiàn)硬盤故障等問題(生產(chǎn)環(huán)境中多次遇到),也會導致數(shù)據(jù)丟失,為了避免單點故障,通常的做法是將數(shù)據(jù)庫復制多個副本以部署在不同的服務器上,這樣即使有一臺服務器出現(xiàn)故障,其他服務器依然可以以最快的速度提供服務。為此,Redis提供了復制(replication)功能,可以實現(xiàn)當一臺數(shù)據(jù)庫中的數(shù)據(jù)更新后,自動將更新的數(shù)據(jù)同步到其他數(shù)據(jù)庫上。

在復制的概念中,數(shù)據(jù)庫分為兩類,一類是主數(shù)據(jù)庫(master),另一類是從數(shù)據(jù)庫(slave)。主數(shù)據(jù)庫可以進行讀寫操作,當寫操作導致數(shù)據(jù)變化時自動將數(shù)據(jù)同步給從數(shù)據(jù)庫。而從數(shù)據(jù)庫一般是只讀的,并接受主數(shù)據(jù)庫同步過來的數(shù)據(jù)。一個主數(shù)據(jù)庫可以擁有多個從數(shù)據(jù)庫。

Redis復制很簡單易用,它通過配置允許slave Redis Servers或者Master Servers的復制品。接下來有幾個關(guān)于redis復制的非常重要特性:

一個Master可以有多個Slaves。

Slaves能通過和其他slave的鏈接,除了可以接受同一個master下面slaves的鏈接以外,還可以接受同一個結(jié)構(gòu)圖中的其他slaves的鏈接。

redis復制是在master段是非阻塞的,這就意味著master在同一個或多個slave端執(zhí)行同步的時候還可以接受查詢。

復制在slave端也是非阻塞的,假設你在redis.conf中配置redis這個功能,當slave在執(zhí)行的新的同步時,它仍可以用舊的數(shù)據(jù)信息來提供查詢,否則,你可以配置當redis slaves去master失去聯(lián)系是,slave會給發(fā)送一個客戶端錯誤。

為了有多個slaves可以做只讀查詢,復制可以重復2次,甚至多次,具有可擴展性(例如:slaves對話與重復的排序操作,有多份數(shù)據(jù)冗余就相對簡單了)。

通過復制可以避免master全量寫硬盤的消耗:只要配置 master 的配置文件redis.conf來“避免保存”(注釋掉所有”save”命令),然后連接一個用來持久化數(shù)據(jù)的slave即可。但是這樣要確保masters 不會自動重啟(更多內(nèi)容請閱讀下段)

Redis復制配置

在Redis中使用復制功能非常容易,只需要在從數(shù)據(jù)庫的配置文件中加入“slaveof 主數(shù)據(jù)復制 主數(shù)據(jù)庫端口”即可。

主數(shù)據(jù)庫無需進行任何配置。下面先來看看一個最簡化的復制系統(tǒng),我們在一臺服務器上啟動兩個redis示例,監(jiān)聽在不同的端口,其中一個作為主數(shù)據(jù)庫,另一個作為從數(shù)據(jù)庫。

首先我們不加任何參數(shù)來啟動一個redis實例作為主數(shù)據(jù)庫:

$ redis-server --port 6379 &

該實例默認監(jiān)聽6379端口,然后加上slaveof參數(shù)啟動另一個redis實例作為從數(shù)據(jù)庫,并讓其監(jiān)聽6380端口:

$ redis-server --port 6380 --slaveof 127.0.0.1 6379 &

查看一下實例的啟動情況:

$ ps aux | grep redis
root      2886  0.0  0.0  38652  4448 pts/0    Sl   16:57   0:00 redis-server *:6379
root      2889  0.0  0.0  36604  4368 pts/0    Sl   16:57   0:00 redis-server *:6380

此時在主數(shù)據(jù)庫中的任何數(shù)據(jù)變化都會自動同步到從數(shù)據(jù)庫中,我們打開redis-cli實例A并連接到數(shù)據(jù)庫:

$ redis-cli -p 6379

再打開redis-cli實例B并連接到從數(shù)據(jù)庫:

$ redis-cli -p 6380

這時我們使用INFO命令來分別在實例A和實例B中獲取replication的相關(guān)信息。

127.0.0.1:6379> INfo replication# Replicationrole:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=266,lag=1
master_repl_offset:266
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:265

可以看到,實例A的角色(role)是master,即主數(shù)據(jù)庫,同時已連接的從數(shù)據(jù)庫(connectd_slaves)的個數(shù)為1個。

同樣在實例B中獲取響應的信息為:

127.0.0.1:6380> INfo replication# Replicationrole:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:378
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

可以看到,實例B的role是slave,即從數(shù)據(jù)庫,同時其主數(shù)據(jù)庫的地址為127.0.0.1,端口為6379。

然后我們在實例A中使用SET命令設置一個鍵的值:

127.0.0.1:6379> set foo bar
OK

此時在實例B中就可以獲得該值了:

127.0.0.1:6380> get foo"bar"

證明兩個Redis實例的復制功能已經(jīng)可用了。默認情況,從數(shù)據(jù)庫是只讀的,如果直接修改從數(shù)據(jù)庫的數(shù)據(jù)會出現(xiàn)錯誤,如下:

127.0.0.1:6380> set foo hey
(error) READONLY You can't write against a read only slave.

但也可以通過設置從數(shù)據(jù)庫的配置文件中的slave-read-only=no,以使從數(shù)據(jù)庫可寫,但是因為對從數(shù)據(jù)庫的任何更改都不會同步給任何其他數(shù)據(jù)庫,并且一旦主數(shù)據(jù)庫中的更新了賭贏的數(shù)據(jù)就會覆蓋從數(shù)據(jù)庫中的改動,所以通常場景下不應該設置從數(shù)據(jù)庫可寫,以免導致易被忽略的潛在應用邏輯錯誤。

配置多臺從數(shù)據(jù)庫的方法也一樣,在所有的從數(shù)據(jù)庫的配置文件中都加上salveof參數(shù)指向同一個主數(shù)據(jù)庫即可。除了通過配置文件或命令行參數(shù)設置slaveof參數(shù)外,還可以在運行時使用slaveof命令修改,下面我們再添加一個實例C(6381):

$ redis-server --port 6381 &
$ redis-cli -p 6381
127.0.0.1:6381> slaveof 127.0.0.1 6379
127.0.0.1:6381> get foo"bar"

如果該數(shù)據(jù)庫已經(jīng)是其他主數(shù)據(jù)庫的從數(shù)據(jù)庫了,slaveof命令會停止和原來數(shù)據(jù)庫的同步轉(zhuǎn)而和新數(shù)據(jù)庫同步,此外對于從數(shù)據(jù)庫來說,還可以使用slaveof no one命令來使當前數(shù)據(jù)庫停止接收其他數(shù)據(jù)庫的同步并轉(zhuǎn)換成為主數(shù)據(jù)庫。如下測試,在從庫實例C上寫入數(shù)據(jù)時時不允許的,然后使用slaveof no one將此數(shù)據(jù)庫轉(zhuǎn)換為主數(shù)據(jù)庫,然后再寫入數(shù)據(jù)就沒有問題了。一般用于但主節(jié)點掛掉的時候,立刻把從節(jié)點切換為主節(jié)點提供數(shù)據(jù)操作服務。

127.0.0.1:6381> set foo bar
(error) READONLY You can't write against a read only slave.
127.0.0.1:6381> SLAVEOF no one
5493:M 07 Aug 17:23:06.792 # Connection with master lost.
5493:M 07 Aug 17:23:06.792 * Caching the disconnected master state.
5493:M 07 Aug 17:23:06.792 * Discarding previously cached master state.
5493:M 07 Aug 17:23:06.792 * MASTER MODE enabled (user request from 'id=2 addr=127.0.0.1:40825 fd=6 name= age=348 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=slaveof')
2886:M 07 Aug 17:23:06.792 # Connection with slave 127.0.0.1:6381 lost.
OK
127.0.0.1:6381> set foo bar
OK

復制常用參數(shù)

slaveof

將當前server做為slave,并為其指定master信息。

masterauth

以認證的方式連接到master,如果master中使用了”密碼保護”,slave必須交付正確的授權(quán)密碼,才能連接成功?!眗equirepas”配置項指定了當前server的密碼。此配置項中值需要和master機器的”requirepas”保持一致。此參數(shù)配置在slave端。

slave-serve-stale-data yes

如果當前server是slave,那么當slave與master失去通訊時,是否繼續(xù)為客戶端提供服務,”yes”表示繼續(xù),”no”表示終止。在”yes”情況下,slave繼續(xù)向客戶端提供只讀服務,有可能此時的數(shù)據(jù)已經(jīng)過期。在”no”情況下,任何向此server發(fā)送的數(shù)據(jù)請求服務(包括客戶端和此server的slave)都將被告知”error”。

slave-read-only yes

slave是否為”只讀”,強烈建議為”yes”。

repl-ping-slave-period 10

slave向指定的master發(fā)送ping消息的時間間隔(秒),默認為10。

repl-timeout 60

slave與master通訊中,最大空閑時間,默認60秒,超時將導致連接關(guān)閉。

repl-disable-tcp-nodelay no

slave與master的連接,是否禁用TCP nodelay選項。”yes”表示禁用,那么socket通訊中數(shù)據(jù)將會以packet方式發(fā)送(packet大小受到socket buffer限制),可以提高socket通訊的效率(tcp交互次數(shù)),但是小數(shù)據(jù)將會被buffer,不會被立即發(fā)送,對于接受者可能存在延遲?!眓o”表示開啟tcp nodelay選項,任何數(shù)據(jù)都會被立即發(fā)送,及時性較好,但是效率較低。建議為”no”。

slave-priority 100

適用Sentinel模塊(unstable,M-S集群管理和監(jiān)控),需要額外的配置文件支持。slave的權(quán)重值,默認100。當master失效后,Sentinel將會從slave列表中找到權(quán)重值最低(>0)的slave,并提升為master。如果權(quán)重值為0,表示此slave為”觀察者”,不參與master選舉。

了解Redis的復制原理

了解Redis復制的原理對運維Redis過程中有很大的幫助,包括如何規(guī)劃節(jié)點,如果處理節(jié)點故障等。下面介紹Redis實現(xiàn)復制的工程。 Redis主從技術(shù)的示例分析

當一個從數(shù)據(jù)庫啟動后,會向主數(shù)據(jù)庫發(fā)送SYNC命令,同時主數(shù)據(jù)庫接收到SYNC命令后會開始在后臺保存快照(即RDB持久化的過程),并將保存快照期間接收到的命令緩存起來,當快照完成后,Redis Master會將快照文件發(fā)送給從數(shù)據(jù)庫,從數(shù)據(jù)庫收到后,會載入快照文件。之后Redis Master會以Redis命令協(xié)議的格式,將寫命令緩沖區(qū)中積累的所有內(nèi)容都發(fā)送給從服務器。以上過程稱為復制初始化,復制初始化結(jié)束后,主數(shù)據(jù)庫每當收到寫命令時就會將命令同步給從數(shù)據(jù)庫,從而保證主從數(shù)據(jù)庫數(shù)據(jù)一致。

你可以通過telnet命令來親自驗證這個同步過程:首先連上一個正在處理命令請求的Redis服務器,然后向它發(fā)送SYNC命令,過一陣子,你將會看到telnet會話接收到服務器發(fā)來的大段數(shù)據(jù)(.rdb文件),之后還會看到,所有的服務器執(zhí)行過的寫命令,都會重新發(fā)送到telnet會話來。

當主從數(shù)據(jù)庫之間的連接斷開重連后,Redis 2.6以及之前的版本會重新進行復制初始化(即主數(shù)據(jù)庫重新保存快照并傳送給從數(shù)據(jù)庫),即使從數(shù)據(jù)庫可以僅有幾條命令沒有收到,主數(shù)據(jù)庫也必須要將數(shù)據(jù)庫里的所有數(shù)據(jù)重新傳送給從數(shù)據(jù)庫。這使得主從數(shù)據(jù)庫斷線重連后的數(shù)據(jù)恢復過程效率很低下,在網(wǎng)絡環(huán)境不好的時候這一問題尤其明顯,Redis 2.8版本的一個重要改進就是斷線重連能夠支持有條件的增量數(shù)據(jù)傳輸,當從數(shù)據(jù)庫重新連接上主數(shù)據(jù)庫后,主數(shù)據(jù)庫只需要將斷線期間執(zhí)行的命令傳送給從數(shù)據(jù)庫,從而大大提高Redis復制的實用性。

增量復制的實現(xiàn),基于以下3點:

1)從數(shù)據(jù)庫會存儲主數(shù)據(jù)庫的運行ID(run id),每個Redis運行實例均會擁有一個唯一的運行ID,每當實例重啟后,就會自動生成一個新的運行ID。

2)在復制同步階段,主數(shù)據(jù)庫每將一個命令傳送給從數(shù)據(jù)庫時,都會同時把該命令存放到一個積壓隊列(backlog)中,并記錄下當前積壓隊列中存放的命令的偏移量范圍。

3)同時,從數(shù)據(jù)庫接收到主數(shù)據(jù)庫傳來的命令時,會記錄下該命令的偏移量。

這三點是實現(xiàn)增量復制的基礎,當主從連接準備就緒后,從數(shù)據(jù)庫會發(fā)送一條SYNC命令來告訴主數(shù)據(jù)庫可以開始把所有數(shù)據(jù)同步過來了。而2.8版本之后,不再發(fā)送SYNC命令,取而代之的是發(fā)送PSYNC,格式為“PSYNC 主數(shù)據(jù)庫的運行ID 斷開前最新的命令偏移量”。主數(shù)據(jù)庫收到PSYNC命令后,會執(zhí)行以下判斷來決定此次重連是否可以執(zhí)行增量復制。

1)首先主數(shù)據(jù)庫會判斷從數(shù)據(jù)庫傳送來的運行ID是否和自己的運行ID相同,這一步驟的意義在于確保從數(shù)據(jù)庫之前確實是和自己同步的,以免從數(shù)據(jù)庫拿到錯誤的數(shù)據(jù)(如主數(shù)據(jù)庫在斷連期間重啟過,會造成數(shù)據(jù)的不一致性)。

2)然后判斷從數(shù)據(jù)庫最后同步成功的命令偏移量是否在積壓隊列中,如果在則可以執(zhí)行增量復制,并將積壓隊列中相應的命令發(fā)送給從數(shù)據(jù)庫。

如果此次重連不滿足增量復制的條件,主數(shù)據(jù)會進行一次全部同步(即與Redis 2.6的過程相同),大部分情況下,增量復制的過程對開發(fā)者來說是完全透明的,開發(fā)者不需要關(guān)心增量復制的具體細節(jié),2.8版本的主數(shù)據(jù)庫也可以正常地和舊版本的從數(shù)據(jù)庫同步(通過接收SYNC命令),同樣2.8版本的從數(shù)據(jù)庫也可以與舊版本的主數(shù)據(jù)庫同步(通過發(fā)送SYNC命令),唯一需要開發(fā)者設置的就是積壓隊列的大小了。

積壓隊列在本質(zhì)上是一個固定長度的循環(huán)隊列,默認情況下積壓隊列的大小為1MB,可以通過配置文件的repl-backlog-size選項來調(diào)整。很容易理解的是,積壓隊列越大,其允許的主從數(shù)據(jù)庫斷線的時間就越長。根據(jù)主從數(shù)據(jù)庫之間的網(wǎng)絡狀態(tài),設置一個合理的積壓隊列很重要。因為積壓隊列存儲的內(nèi)容是命令本身,如 SET FOO BAR,所以估算積壓隊列的大小只需要估計主從數(shù)據(jù)庫斷線的時間中主從數(shù)據(jù)庫可能執(zhí)行的命令的大小即可。與積壓隊列相關(guān)的另一個配置選項是repl-backlog-ttl,即當所有主從數(shù)據(jù)庫與主數(shù)據(jù)斷開連接后,經(jīng)過多久時間可以釋放積壓隊列的內(nèi)存空間,默認時間是1小時。

從數(shù)據(jù)庫持久化

另一個相對耗時的操作是持久化,為了提高性能,可以通過復制功能建立一個或多個從數(shù)據(jù)庫,并在從數(shù)據(jù)庫中啟用持久化,同時在主數(shù)據(jù)庫禁用持久化,當從數(shù)據(jù)庫崩潰重啟后主數(shù)據(jù)庫會自動將時間同步過來,所以無需擔心數(shù)據(jù)丟失。

然后當主數(shù)據(jù)庫崩潰時,情況就稍顯復雜了。手工通過從數(shù)據(jù)庫數(shù)據(jù)恢復主數(shù)據(jù)庫數(shù)據(jù)時,需要嚴格按照以下兩步進行:

1)在從數(shù)據(jù)庫中使用SLAVEOF NO ONE命令將從數(shù)據(jù)庫提升為主數(shù)據(jù)庫繼續(xù)服務。

2)啟動之前崩潰的主數(shù)據(jù)庫,然后使用SLAVEOF命令將其設置成新的主數(shù)據(jù)庫的從數(shù)據(jù)庫,即可將數(shù)據(jù)同步回來。

注意,當開啟復制且主數(shù)據(jù)庫關(guān)閉持久化的時候,一定不要使用supervisor以及類似的進程管理工具令主數(shù)據(jù)庫崩潰后自動重啟。同樣當主數(shù)據(jù)庫所在的服務器因故關(guān)閉時,也要避免直接重新啟動。這是因為當主數(shù)據(jù)庫重新啟動后,因為沒開持久化功能,所以數(shù)據(jù)庫中所有數(shù)據(jù)都被清空,這時從數(shù)據(jù)庫依然會從主數(shù)據(jù)庫中接收數(shù)據(jù),使得所有從數(shù)據(jù)庫也被清空,導致從數(shù)據(jù)庫的持久化失去意義。

無論哪種情況,手工維護從數(shù)據(jù)庫或主數(shù)據(jù)的重啟以及數(shù)據(jù)恢復都相對麻煩,好在Redis提供了一種自動化方案哨兵來實現(xiàn)這一過程,避免了手工維護的麻煩和容易出錯的問題。

無硬盤復制

上面介紹了Redis復制的工作原理時介紹了復制是基于RDB方式的持久化實現(xiàn)的,即主數(shù)據(jù)庫端在后臺保存了RDB快照,從數(shù)據(jù)庫端則接收并載入快照文件,這樣的實現(xiàn)有點是可以顯著地簡化邏輯,復用已有的代碼,但是缺點也很明顯。

1)當主數(shù)據(jù)庫禁用RDB快照時(即刪除了所有的配置文件中的save語句),如果執(zhí)行了復制初始化操作,Redis依然會生成RDB快照,所以下次啟動后主數(shù)據(jù)庫會以該快照恢復數(shù)據(jù)。因為復制發(fā)生的時間不能確定,這使得恢復的數(shù)據(jù)可能是任何時間點的。

2)因為復制初始化時需要在硬盤中創(chuàng)建RDB快照文件,所以如果硬盤性能很慢時這一過程會對性能產(chǎn)生影響。舉例來說,當使用Redis做緩存系統(tǒng)時,因為不需要持久化,所以服務器的硬盤讀寫速度可能較差。但是當該緩存系統(tǒng)使用一主多從的集群架構(gòu)時,每次和從數(shù)據(jù)庫同步,Redis都會執(zhí)行一次快照,同時對硬盤進行讀寫,導致性能下降。

因此從2.8.18版本開始,Redis引入了無硬盤復制選項,開啟該選項時,Redis在與從數(shù)據(jù)庫進行復制初始化時將不會將快照內(nèi)容存儲到硬盤上,而是直接通過網(wǎng)絡發(fā)送給從數(shù)據(jù)庫,避免了硬盤的性能瓶頸??梢栽谂渲梦募惺褂萌缦屡渲脕黹_啟該功能:

repl-diskless-sync yes

PS:當需要把Slave轉(zhuǎn)換為Master時可以使用”SLAVEOF ON ONE”指令。

以上是“Redis主從技術(shù)的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

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

AI