Redis 主從複製原來這麼簡單
- 2020 年 3 月 4 日
- 筆記
什麼是redis主從複製
眾所周知redis之所以火因為它有著讀取速度快,可持久化的優點。redis的持久化保證了斷電或重啟數據不會丟失。但僅僅這樣是不夠的的,持久化是將數據定期寫入磁碟中,萬一哪一天這一台伺服器掛掉了,那所有數據依舊會丟失。為了解決這個單點故障問題,所以就有了主從複製。
主從複製就是 將一台redis伺服器的數據自動的複製到其他redis伺服器上。一台伺服器出故障的概率很高,但是多台伺服器同時出故障的概率就很低了吧。所謂主從主從,當然是有主伺服器 (master) 和從伺服器 (slave) 啦,一個 master 可以將數據複製到多個 slave,但是特別注意的是,複製是單向的,只能從 master 到 slave 。一個master 可以有多個 slave ,一個slave 也可以有多個slave ,但是一個 slave 只能從屬一個master 。如下圖這樣就是錯誤的。

主從複製的作用及場景
1、數據冗餘:主從複製實現了數據的熱備份,相當於一份數據在多個伺服器上存儲了,是持久化之外的一種數據冗餘方式,這樣做的目的是以空間換取安全性。如果主伺服器掛掉了,可以通過從服務將數據恢復。
2、故障快速修復:當 master 出現問題的時候,可以快速的將一個 slave 切換成 master 繼續提供服務 ,保證項目穩定性。
3、讀寫分離:主從複製實現讀寫分離非常簡單,寫入的時候只操作 master ,讀取的時候只操作 slave ,這樣讀的話可以多個slave 滿足項目高並發的操作。
4、負載均衡:既然實現了讀寫分離,當然就能實現負載均衡,多個 slave 承擔 數據讀取操作 ,從而分擔 master 伺服器的壓力。
5、高可用的基石:主從複製還是哨兵模式和集群模式能夠實施的基礎。
既然主從複製有這些作用,那在實際應用中會用在哪些場景呢?
1、如果項目對數據安全性穩定性要求較高,就會使用主從複製搭建哨兵模式或者搭建集群。
2、海量數據讀寫,需要做讀寫分離提高防蚊效率,就會用到主從複製
3、容災恢復,如果對數據依賴度很高,害怕數據在伺服器掛掉後丟失,就可以通過主從複製防止數據丟失。
主從複製的模式
一主一從
這種模式在實際應用中還是比較少見的其實,一主一從主要是實現讀寫分離和容災恢復。考慮到成本的問題,所以採用兩台伺服器,一個redis伺服器master 負責讀操作,並定期的複製到 另個一伺服器slave 。slave 伺服器負責讀寫操作。在項目中配置的時候配置兩個redis連接。
一主多從
一主多從有可以分為幾種,如下圖:

這種就是所有的 slave 都從 master 中 進行複製,這樣的好處是 配置簡單,所有的slave 都只用關係 master 就好了,但是要考慮到其實複製也是會侵佔CPU記憶體的,所有的slave 都從 master 複製,可能增大 master的負荷。
再來看看下圖


這種模式也是一主多從,但是和上面的所有的 slave 都從 master 複製不一樣。它是使一個到兩個slave 從master 直接複製,其他的slave 從這兩個slave 中複製。存在層級關係。這樣的好處的降低的master 伺服器的負荷,但是這樣會導致如果中間某個 slave 掛掉了,那依附於它的所有slave 都不能用了。
主從複製部署
這裡我使用的是Ubuntu安裝的redis,redis怎麼安裝,可以看我這篇文章 Redis安裝 安裝好redis後,我們啟動看看是否正常
redis-server /usr/local/redis/etc/redis.conf redis-cli -a 123456

證明是redis是正常啟動的,那現在怎麼配置主從模式呢?
按理說主次模式的redis伺服器當然是搭建在不同的伺服器上,但是我們條件有限,我這裡的三台redis服務都搭建在一個伺服器上,只是他們監聽的埠不同。
1、修改redis.conf
我們先修改master的配置文件redis.conf 的一些配置
bind 0.0.0.0 表示可以被所有機器訪問。 daemonize yes 表示可以後台啟動 port 6379 pidfile /var/run/redis_6379.pid logfile "/usr/local/redis/logs/log_redis.log" requirepass 123456


2、複製兩份redis.config
改好redis.conf 後,將/usr/local/redis/etc/ 目錄下的redis.config 複製兩份為redis_slave1.conf redis_slave2.config

3、修改rdis_slave1.conf
bind 本機ip 表示只能本機訪問 daemonize yes port 6389 pidfile /var/run/redis_6389.pid logfile "/usr/local/redis/logs/log_redis_slaveof6389.log" requirepass 123456 ---上面的這些配置和redis.conf中基本一樣修改一下就好了,日誌是為了方便查看。下面看重點配置 slaveof 192.168.252.53 6379 設置master的ip 和port masterauth 123456 設置master的登錄密碼,就是redis.conf 中配置的requirepass


4、修改redis_slave2.conf
同樣的
bind 192.168.252.53 daemonize yes port 6399 pidfile /var/run/redis_6399.pid logfile "/usr/local/redis/logs/log_redis_slaveof6399.log" requirepass 123456 slaveof 192.168.252.53 6379 masterauth 123456
5、啟動redis服務
redis-server /usr/local/redis/etc/redis.conf redis-server /usr/local/redis/etc/redis_slaveof1.conf redis-server /usr/local/redis/etc/redis_slaveof2.conf
查看一下進程
ps -ef | grep redis

6、啟動客戶端
都啟動來了,現在連到單個redis伺服器看看
主服務 redis-cli -a 123456 從服務 redis-cli -h 192.168.252.53 -p 6389 -a 123456 redis-cli -h 192.168.252.53 -p 6399 -a 123456


7、測試
啟動3台客戶端,分別連上master和兩個slave 在master中
set c 122

在slave1和slave2 中分別
get c


這樣就說明你的主從複製服務已經搭建好啦。
8、問題記錄
上面的是一個完美的過程搭建的主從複製的例子,但是我相信在實際搭建的時候肯定會出現各種問題,現在記錄下我搭建的時候出現的問題吧 1、許可權問題 在搭建好主從服務後,進入從節點查看info replication發現
master_link_status:down
表明主從節點並沒有建立連接,但是但是為什麼一直是down 呢,看了一下日誌

提示不能打開rdb這個快照,當然就不能將內容複製到從節點啦,再一看這個路徑,是我自己建的路徑,第一反應就是許可權問題,然後進這個目錄一看,發現我的etc目錄是root用戶的。所以就修改了文件的用戶和用戶組。在進到etc目錄下,就發現了兩個快照,再去看的時候發現down變成up 了。
quellanan@quellanan-Lenovo-G400:/usr/local/redis$ sudo chown quellanan etc [sudo] quellanan 的密碼: quellanan@quellanan-Lenovo-G400:/usr/local/redis$ sudo chgrp quellanan etc quellanan@quellanan-Lenovo-G400:/usr/local/redis$ ll 總用量 20 drwxr-xr-x 5 root root 4096 8月 8 16:50 ./ drwxr-xr-x 13 root root 4096 8月 1 16:28 ../ drwxr-xr-x 2 root root 4096 8月 1 16:57 bin/ drwxr-xr-x 2 quellanan quellanan 4096 8月 15 09:50 etc/ drwxrwxrwx 2 root root 4096 8月 15 09:16 logs/ quellanan@quellanan-Lenovo-G400:/usr/local/redis$ cd etc/ quellanan@quellanan-Lenovo-G400:/usr/local/redis/etc$ ll 總用量 196 drwxr-xr-x 2 quellanan quellanan 4096 8月 15 09:50 ./ drwxr-xr-x 5 root root 4096 8月 8 16:50 ../ -rw-r--r-- 1 quellanan quellanan 188 8月 15 09:50 dump6389.rdb -rw-rw-r-- 1 quellanan quellanan 188 8月 15 09:50 dump.rdb -rw-rw-r-- 1 quellanan quellanan 58810 8月 14 09:18 redis.conf -rw-rw-r-- 1 quellanan quellanan 58882 8月 14 09:16 redis_slaveof1.conf -rw-r--r-- 1 quellanan quellanan 58882 8月 15 09:11 redis_slaveof2.conf
許可權問題我感覺還是挺大的,因為我們一般都是遠程到伺服器上操作,所以用戶許可權很多都需要注意。
2、還有一個也是發現master_link_status:down,但是並不是用戶許可權問題導致的,查看一下防火牆的狀態,將防火牆關閉了試試。
ufw status 查看防火牆狀態 ufw enable 開啟防火牆 ufw disable 關閉防火牆
3、在主節點插入數據的時候出現問題
127.0.0.1:6379> set a 1qaz (error) MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.
執行這個
127.0.0.1:6379> config set stop-writes-on-bgsave-error no OK 127.0.0.1:6379> set a 123456 OK 127.0.0.1:6379> get a "123456"
主從複製的原理
上面以及搭建了一個主從複製的樣例,是一主兩從的,那是怎麼redis是怎麼具體實現的呢? 在將原理之前,先來看看主從複製的幾個概念。啟動master後
127.0.0.1:6379> info server # Server redis_version:4.0.9 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:514e9a11b2a67dfc redis_mode:standalone os:Linux 5.0.0-23-generic x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:atomic-builtin gcc_version:7.4.0 process_id:19688 run_id:136de716105e54294144003a881ba29cdfbccfb2 tcp_port:6379 uptime_in_seconds:4515 uptime_in_days:0 hz:10 lru_clock:5556386 executable:/usr/local/redis/etc/redis-server config_file:/usr/local/redis/etc/redis.conf
這個run_id 就是redis服務的唯一標識,重啟redis服務號,這個run_id 會改變,多個redis客戶端連接到同一個服務端,其run_id 是一樣的,也就是說run_id 指的是服務端的id
127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.252.53,port=6389,state=online,offset=5541,lag=1 slave1:ip=192.168.252.53,port=6399,state=online,offset=5541,lag=0 master_replid:f0c89aa8040dfe869de82ee623a1212240456d76 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:5541 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:5541
其中repl_backlog_size 複製快取區大小,默認大小為1M,如果mater_repl_offset在這個範圍內,就看是部分複製,否則就開始全量複製。
全量複製
先看下圖,圖畫的不是很好見諒

1、首先slave會向 master發送一個 psync 命令,因為是第一次,所以不知道run_id 和offset,所以傳過來-1表示全量複製
2、 master在接收到psync 後,將run_id 和offset 發送給slave,slave存儲起來
3、master進行bgsave生成rdb ,並將rdb 文件發送給slave
4、在bgsave 和send rdb 的過程中可能會產生write 的數據,那麼就會把數據存到repl_back_buffer 中 並將buffer發送給slave .
5、slave 會清空就數據,然後載入rdb和buffer 將數據存儲起來。
部分複製

既然是部分複製,那就是slave已經知道了master的run_id 和offset ,所以發送psync 命令帶上這兩個參數,master 就知道這是部分複製,然後通過偏移量將需要複製的數據發送給slave。
總結
主從複製的過程中既用到了全量複製也用到了部分複製,二者是相互配合使用的。看下面的流程圖:

還有一點需要注意的是,如果master 重啟了,那麼它的run_id發生了改變,那麼依賴它的slave都會進行一次全量複製後在進行部分複製。
哨兵模式
哨兵模式介紹
在將哨兵模式之前,先來說說主從複製的缺點吧。
如果主節點出了問題,那麼主節點不在提供服務,需要手動的將從節點切換成主節點。
所以這個時候哨兵模式就出現啦,當主節出現故障時,Redis Sentinel會自動的發現主節點的故障並轉移,並通知應用方,實現高可用。
下面是Redis官方文檔對於哨兵功能的描述:
1、監控(Monitoring):哨兵會不斷地檢查主節點和從節點是否運作正常。
2、自動故障轉移(Automatic failover):當主節點不能正常工作時,哨兵會開始自動故障轉移操作,它會將失效主節點的其中一個從節點升級為新的主節點,並讓其他從節點改為複製新的主節點。
3、配置提供者(Configuration provider):客戶端在初始化時,通過連接哨兵來獲得當前Redis服務的主節點地址。
4、通知(Notification):哨兵可以將故障轉移的結果發送給客戶端。
哨兵模式的結構拓撲圖大概如下,也是照書上畫的哈哈

大意就是
1、每一個哨兵節點會監聽其他的哨兵節點以及master 和所有的slave
2、所有哨兵節點會定期的ping 主節點,監控是否正常
3、如果認為主節點出現故障的哨兵數量達到闕zhi,就判定主節點死掉,主節點就會客觀下線
4、主節點客觀下線後,哨兵節點通過選舉模式在 slave 中選擇出一個升級為主節點
5、其他的salve 指向新的主節點
6、原來的master 變成 slave ,並且指向新的主節點
引用官方哨兵模式處理流程
每個Sentinel(哨兵)進程以每秒鐘一次的頻率向整個集群中的Master主伺服器,Slave從伺服器以及其他Sentinel(哨兵)進程發送一個 PING 命令。
●如果一個實例(instance)距離最後一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel(哨兵)進程標記為主觀下線(SDOWN)。
●如果一個Master主伺服器被標記為主觀下線(SDOWN),則正在監視這個Master主伺服器的所有 Sentinel(哨兵)進程要以每秒一次的頻率確認Master主伺服器的確進入了主觀下線狀態。
●當有足夠數量的 Sentinel(哨兵)進程(大於等於配置文件指定的值)在指定的時間範圍內確認Master主伺服器進入了主觀下線狀態(SDOWN), 則Master主伺服器會被標記為客觀下線(ODOWN)。
●在一般情況下, 每個 Sentinel(哨兵)進程會以每 10 秒一次的頻率向集群中的所有Master主伺服器、Slave從伺服器發送 INFO 命令。
●當Master主伺服器被 Sentinel(哨兵)進程標記為客觀下線(ODOWN)時,Sentinel(哨兵)進程向下線的 Master主伺服器的所有 Slave從伺服器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
●若沒有足夠數量的 Sentinel(哨兵)進程同意 Master主伺服器下線, Master主伺服器的客觀下線狀態就會被移除。若 Master主伺服器重新向 Sentinel(哨兵)進程發送 PING 命令返回有效回復,Master主伺服器的主觀下線狀態就會被移除。
哨兵模式部署
1、首先到我們redis安裝目錄下,發現有sentinel.conf ,我們把它移到我們自己定義的文件夾中,和redis.conf 放在一起。
mv sentinel.conf /usr/local/redis/etc/

2、修改sentinel.conf文件
port 26379 dir /usr/local/redis/etc 這裡默認的是「/tmp」,如果你沒有這個目錄的許可權就需要換啦,換一個你有許可權的目錄,不然後果自負哈哈,我就是從坑裡爬起來的 sentinel monitor mymaster 192.168.252.53 6379 2 sentinel auth-pass mymaster 123456 設置監控的主節點,2是一個閾值,代表有兩台或兩台以上哨兵判斷主節點redis不通的話就認定這個節點有問題,實行故障轉移。 daemonize yes 後台啟動 logfile "/usr/local/redis/logs/redis_sentinel-26379.log" 加上日誌 ,不加也無所謂

注意,這個auth-pass 要放在放在monitor 下面,不然會報錯

配上一些參數說明:

3、將sentinel.conf 複製兩份,分別為sentinel26389.conf,sentinel26399.conf並修改這個文件中的prot 和logfile
port 26389 logfile "/usr/local/redis/logs/redis_sentinel-26389.log" port 26399 logfile "/usr/local/redis/logs/redis_sentinel-26399.log"
4、啟動哨兵
redis-sentinel /usr/local/redis/etc/sentinel.conf redis-sentinel /usr/local/redis/etc/sentinel26389.conf redis-sentinel /usr/local/redis/etc/sentinel26399.conf
查看一下,三個哨兵都已經啟動了。

5、驗證 先看看啟動日誌,,下圖所示表明監控了三個節點。如果沒有監控到這三個節點,證明沒有配置成功。


沒有配置成功的原因可能是防火牆導致的,關閉調防火牆。還有就是如果redis-server重啟過,那在sentinel.conf中生成的pid 和最後的運行添加的幾行需要刪除掉,下圖這些。然後重新運行。


好的,日誌看的沒有問題,如果不想看日誌,我們來這樣驗證,我們已經啟動了三個redis服務,三個哨兵。我們現在把 master 殺死看看是什麼情況。
kill -9 19688
看日誌,三個哨兵的監控日誌基本上是一樣的,下圖貼出三個哨兵的日誌,我們就看一下第一個哨兵的日誌分析一下。

看上圖,啟動哨兵的時候,監控到了master 6379 和兩個slave 6389和6399,以及另外兩個哨兵,26389和26399.
然後sdown master mymaster 192.168.252.53 6379 表示剛剛我們殺死的master服務。
這個時候有一個哨兵表示其主觀下線,等到odown 達到我們設置的2時,表明有兩個哨兵表示其主觀下線,那麼就認為6379這個master 已經客觀下線。
然後通過選舉,選取26399 這個哨兵為這三個哨兵的領導者(leader)。
23699 這個leader 在salve中選擇6399轉為 master
將6389 這個slave 指向新的 master 6399
這個時候重啟6379 這個redis服務
將6379 這個slave指向新的master 6399


好,下面我們來看看介面


可以看到master已經切換到6399 服務了,現在我們再切換一下,看下面這張圖應該很清晰啦

到此為止,哨兵模式就搭建好啦,當 master 掛掉時,會自動的將一個slave 升級成 master 並將其他的 slave 指向新的master ,從新把原來的master啟動後,會變成slave 執行新的master 。
總結
寫到這,其實還有一部分沒有寫完,但是感覺實在是太長了,就先寫這麼多吧,還差一個怎麼在項目中使用搭建的哨兵模式,也就是集群模式,怎麼做到讀寫分離,實現高可用的。
因為前面這些講的都是在redis資料庫上直接操作,那現在部署好了,怎麼在項目程式碼中使用呢,所以下篇接著將在項目中怎麼使用redis集群。喜歡的小夥伴可以持續關注啦。
好了,上面都是題外話,下面總結一下這篇文章吧。
1、主從複製是什麼以及作用。
2、怎樣部署一個主從複製(案例一主兩從)
3、怎樣部署哨兵模式(三哨兵)
其實我感覺如果你通過這篇文章學會了這三點,就夠了,其他的看看當了解。
謝謝大家
看到這的小夥伴,對文章有什麼建議趕緊提出來吧!這一期想寫 redis 的。從 redis 安裝到redis 簡單使用,redis主從複製,redis 持久化,哨兵模式,集群模式。由淺及深圖文講解幫助大家全面深刻的了解reidis 知識。如果大家感興趣可以持續關注。覺得好看記得分享喲❤
