1. 程式人生 > >Redis主從是如何維持TCP連線並且檢測異常斷鏈?

Redis主從是如何維持TCP連線並且檢測異常斷鏈?

最近專案需要,所以研究了一下Redis主從的TCP連結是如何維持的,發現這一塊還沒有資料說明過,所以就把打算把這個東西記錄一下分享出來。

這個問題可以拆成以下幾個部分來說,包括:

  • Redis如何建立主從關係
  • Redis如何檢測斷鏈
  • Redis如何重新建立主從關係

下面一一說明。

一、Redis如何建立主從關係

redis使用slaveof ip host指令來建立主從關係,主從關係的建立會引發持續的資料同步。值得一提的是,redis的設計認為這個關係的建立是持續性的,所以也設計了重連機制、對master的驗證機制、高效的資料重新同步的方法。下面具體描述這個過程及提到的幾個概念。

建立主從關係

前備條件:
例項A:127.0.0.1 6379
例項B:127.0.0.1 6380
我們希望例項A實時備份例項B,所以我們對例項A傳送指令slaveof 127.0.0.1 6380,這個邏輯如下圖所示。

*圖1 slaveofCommand指令傳送與執行過程

  • redis-cli傳送指令slaveof 127.0.0.1 6379
  • redis-server_6379接收slaveof 127.0.0.1 6379,執行slaveofCommand指令,將ip及port寫到server結構體裡,並修改狀態標誌位,同時回覆OK
  • redis-server_6379執行周期函式serverCron
    ,其中會執行函式replicationCron,這裡會檢測狀態標誌位,並呼叫connectWithMaster,這個函式最後會呼叫非阻塞的connect,並且安裝事件處理函式syncWithMaster,當連線成功後,syncWithMaster被呼叫,啟動與Master的同步協議或者是連線失敗處理,如果是失敗,則後續會一直嘗試重連,所以我們會看到主從建立連線失敗的情況下syncWithMaster每秒都會被執行一次。

二、Redis如何檢測斷鏈

斷鏈這個問題比較複雜,需要考慮較多的情況,包括正常關閉、半開啟、異常關閉,底層的網路程式設計一般來說都跑不開這幾個話題,redis使用c語言作為開發語言,自己開發了一套IO複用機制,把這幾個問題處理得很好,這裡我不打算再敘述這幾個問題,下面直奔主題。

1、主監測從

主從關係建立後,redis從會以1秒為週期,向redis主傳送replconf ack offset指令,用以向master表達當前複製偏移量,並且讓master得以以此作為依據判斷redis從是否仍然存活,即心跳機制。

2、從監測主

主從關係建立後,redis主會以repl-ping-slave-period為週期,向redis從傳送PING指令。repl-ping-slave-period可以在配置檔案當中更改,不能小於1,因為replicationCron的週期是1,這是redis能處理的最小定時事件了(這是錯誤的,serverCron的週期才是redis能處理的最小定時事件)。
redis從以此為依據,建立心跳檢測機制。redis從每次收到ping指令,會更新server..master->lastinteraction時間,並且之後每次執行replicationCron都會檢測距離上次主從互動的時間是否超過了repl-timeout,這個也提供在配置檔案當中。如果時間超出了,則redis從認為redis主已經掛掉,則開始清理這個master。
所以我們可以得出結論,redis從基於repl-ping-slave-periodrepl-timeout這兩個配置來建立對於master的檢測機制,前者最小不能小於replicationCron的週期,後者最小不能小於前者。

正常關閉

即Redis主主動發出Fin包,發起TCP關閉的流程。
redis從會為redis主建立客戶端,redis發出Fin包,向redis從傳送一個EOF。當redis從收到Fin包,產生可讀事件,readQureyFromClient被呼叫,最終呼叫read返回0,獲得EOF,感知到對端發起的關閉流程。

半開啟狀態

即對端已經無法通訊,但是本地無法感知到,除非主動發起通訊流程。
這種情況包括:

1、網路不通

2、主Redis程序崩潰或者主機down

3、主Redis主機網線被拿掉

4、中間網路裝置的網路被拿掉

這種情況Redis從需要依賴心跳機制來監測,並且主動發起TCP關閉流程,將[Redis從-->Redis主]方向的TCP連線關閉。
根據我們所描述的從監測主的原理,這個情況都可以被發現。

三、Redis如何重新建立主從關係

Redis從向Redis主重新發起連線

Server結構體定義了masterhost及masterport兩個域,用來儲存master的ip地址與埠。

`struct redisServer {`

    `...`

    `char* server.masterhost;`

    `int masterport;`

    `...`

`}`

當redis接受了slaveof ip port指令後,就將ip及port寫到以上兩個域當中。並且執行server.repl_state = REPL_STATE_CONNECT
爾後在replicationCron函式當中根據根據以上操作,執行connect操作。具體如下:

`replicationCron()`

    `-->connectWithMaster()`

        `-->anetTcpNonBlockBestEffortBindConnect()`

        `-->aeCreateFileEvent()`

`replicationSendAck()`

replicationCron()是Redis惟一的定時事件的處理器,每秒被觸發一次。所以如果從與主斷掉了,從每秒會嘗試重新一次。

但是會嘗試多久,這個還需要再驗證。

每次執行時,會檢查是否需要連線master,如果需要就會呼叫connectWithMaster()
connectWithMaster()使用非阻塞connect()去連線master,並且在connect()返回後馬上綁定了syncWithMaster()
這個地方很精妙,也很體現Redis作者功力的地方。原本我以為syncWithMaster只有在連線成功後才會被繫結到描述符上,但事實並不是這樣。
connect()因為是非阻塞式的,所以我們沒有辦法立即得知是否連線成功了,但是當connect()的結果確定後,核心會反映到描述符上,如果成功則會產生可寫事件,如果失敗就會產生可讀、可寫事件。這個時候利用getsockopt()就可以判斷connect()是否成功了。
這個地方還有一個注意事項,非阻塞式connect()會立即返回-1,但是fd是由sock()建立的,所以這個時候並不是說fd可以用來與遠端伺服器通訊,但是我們的確可以用他來與核心通訊,但是這個fd並不會出現在/proc檔案系統裡。

aeCreateFileEvent()會將anetTcpNonBlockBestEffortBindConnect()產生的fd及可讀、可寫事件與syncWithMaster()繫結到一起,當fd產生可讀可寫事件時,syncWithMaster()執行,如果連線失敗,那麼這個情況就會在syncWithMaster()被處理掉。

相關推薦

Redis主從是如何維持TCP連線並且檢測異常

最近專案需要,所以研究了一下Redis主從的TCP連結是如何維持的,發現這一塊還沒有資料說明過,所以就把打算把這個東西記錄一下分享出來。 這個問題可以拆成以下幾個部分來說,包括: Redis如何建立主從關係 Redis如何檢測斷鏈 Redis如何重新建立主

TCP/IP詳解--TCP異常關閉連線的意義 異常關閉的情況

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

socket心跳超時檢測,快速處理新思路(適用於超大量TCP連線情況下)

假設一種情景:TCP伺服器有1萬個客戶端連線,如果客戶端5秒鐘不發資料,則要斷開。服務端如何檢測客戶端是否超時?這看起來是一個非常簡單的問題,其實不然! 最簡單的處理方法是:啟動一個執行緒,每隔一段時間,檢查每個連線是否超時。每次處理需要1萬次檢查。計算量太大!檢查的時間間隔不能太小,否則大大增

mac下安裝redisredis視覺化工具rdm並且連線redis

一、安裝redis 最最最最簡單和推薦的方法就是使用brew命令安裝,前提是你的mac要安裝brew brew install redis 然後就等安裝完畢就好了 二、安裝rdm 直接安裝rdm dmg檔案 https://pan.baidu.com/s/10vpdhw7YfDD7G4y

TCP連線異常終止(RST包)

轉自:http://blog.csdn.net/ixidof/article/details/8049667 TCP異常終止(reset報文) TCP的異常終止是相對於正常釋放TCP連線的過程而言的,我們都知道,TCP連線的建立是通過三次握手完成的,而TCP正常釋放

redis主從連線不成功錯誤

安裝完redis後,設定主從,在從伺服器上執行 127.0.0.1:6379> slaveof 192.168.159.131 6379 slaveof <主伺服器的IP> <

針對TCP連線異常斷開的分析

        我們知道,一個基於TCP/IP的客戶端-伺服器的程式中,正常情況下,我會是啟動伺服器使其在一個埠上監聽請求,等待客戶端的連線;通過TCP的三次握手,客戶端能夠通過socket建立一個到伺服器的連線;然後,兩者就可以基於這個socket連線通訊了。連線結束後,客戶端(程序)會退出;在不需要繼續處

TCP 連線TCP keep alive 保活檢測機制

生產環境中一臺2核4G的linux伺服器TCP連線數時常保持在5-7w間徘徊,檢視日誌每秒的請求數也就100-200,怎麼會產生這麼大的TCP連線數。檢查了下客戶端上行的HTTP協議,Connection 頭欄位是Keep-Alive,並且客戶端在請求完之後沒有立即關閉連線

php連線redis導致系統對外tcp連線埠太多問題

這段時間在做一個專案中,大量運用到了redis,用了很多後臺程序跑任務。 後臺指令碼是個死迴圈,由於連線redis的類有問題,導致每次進行操作都會進行一次connect,產生一個新連線。一段時間後連線redis的tcp埠過多,超出了系統的預設限制。使用netstat命令檢視

Redis主從同步異常問題記錄

一、背景     2015.7.31 10.36.14.*網段的TOR故障一小時,網路故障恢復後,redis nj多個從主從同步異常:        除slave0外,其他slave的offset均比master大。注:redis的主從之間通過offset進行增量同步,即從

記一次redis主從連線的錯誤

Redis版本 redis-4.0.11 安裝後多例項均可正常使用,將其中一個例項設定為從伺服器後,呼叫info replication報master_link_status:down; 外部原因: 1.因為redis部署在阿里雲伺服器上,首先在阿里雲控制

關於TCP連線極端異常情況的處理方法的思考

這裡說的極端異常情況,不是對方(伺服器或者客戶端)一般的異常情況,即引用該TCP連線的程序異常退出而由OS直接發出FIN或者RST包,從而關閉這個連線。這樣本方會受到SOCKET_ERR返回,或者len=0的資料。 這裡說的極端情況是對方主機或者網路裝置突然斷電造成的連線

nginx+redis主從+tomcat一機多實例實現會話共享

redis session恭喜1、安裝nginx2、用兩個虛擬機安裝兩個reids(reids1、redis2) 其中一個配置slaveof 192.168.1.86 6379(另一個redis的IP與端口)3、安裝兩個tomcat修改tomcat的context.xml: <Context&g

利用Sentinel實現Redis主從切換

edi nbsp ilo bind redis poc 自主 日誌 sent 利用Sentinel(哨兵)實現Redis集群的故障自主切換 首先部署redis主從集群,這裏忽略過程,主要看配置文件: master: bind 0.0.0.0 port 6801 log

redis 主從搭建

redis 主從搭建環境:redis_M 172.16.0.137 redis_S 172.16.0.138 系統:centos6.71、在redis_M 172.16.0.137 、redis_S 172.16.0.138搭建單機redis2、修改配置參數redis.conf主要修改4個參數:portlog

Redis主從集群的Sentinel配置

redis集群 linux sentinel redis哨兵 首先對三臺機器進行redis的單機安裝,然後進行以下步驟master 192.168.1.102slaver 192.168.1.104slaver 192.168.1.105修改兩個slaver的redis.conf配置文件 添加

TCP狀態監控在異常偵測、業務告警中有多重要

tcp連接 監控告警 異常偵測 很多同學在做監控告警、異常偵測時專註於軟件本身的數據,而忽略了TCP連接狀態的監控,其實TCP連接真實的反應了服務器和服務本身的隊列情況,是最靈敏的服務陰晴表。 現在的服務之間都是通過網絡進行通信,而很多服務通信是基於TCP的方式,包括大家 熟悉的HT

redis主從+哨兵模式

strong img 目錄 .html 主從模式 命令 onf 模擬 -s 主從模式配置分為手動和配置文件兩種方式進行配置,我現在有192.168.238.128(CentOS1)、192.168.238.131(CentOS3)、192.168.238.132(CentO

Redis主從復制和集群配置

get 行數據 pattern 額外 監控 redis-cli 客戶端 輸入a stat redis主從復制 概述 1、redis的復制功能是支持多個數據庫之間的數據同步。一類是主數據庫(master)一類是從數據庫(slave),主數據庫可以進行讀寫操作,當發生寫操作的時