1. 程式人生 > >CODIS2 x原理 之 CODIS-PROXY實現原理

CODIS2 x原理 之 CODIS-PROXY實現原理

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                       

作者:鄒祁峰
郵箱:[email protected]
部落格:http://blog.csdn.net/qifengzou


日期:2016.08.02 18:48:39
轉載請註明來自”祁峰”的CSDN部落格

 

程式codis-proxy是連線client與codis-server之間的橋樑,且其主要處理流程充分體現了codis設計思想。要想深入理解codis原理,必須首先弄清楚codis-proxy各主要處理流程。

1 總體時序

Codis-proxy最主要的作用就是接收客戶端提交的redis命令,並將命令分發到後端codis-server叢集,再收集各命令的執行結果,最終將執行結果返回給客戶端。其大體處理時序圖如下:
這裡寫圖片描述

 

功能簡介:
  1.客戶端:Redis命令的發起方
  2.SN-接收協程:用於接收來自客戶端的請求
  3.SN-傳送協程:用於傳送請求處理結果至客戶端
  4.BC-傳送協程:用於將客戶端的請求轉發到後端某codis-server服務
  5.BC-接收協程:用於接收來自某codis-server服務的應答
  6.REDIS服務:某codis-server服務

2 處理流程

2.1 接收客戶端連線

Codis-proxy完成初始化之後,將會啟動一個協程專門用來幀聽埠,並接收來自客戶端的連線請求。
這裡寫圖片描述

 

一旦收到客戶端的連線請求,幀聽協程將tcp連線物件放入連線佇列,另一個協程將會從連線佇列中取出該連線,併為之建立Session物件,再為該Session物件新建一個SN-接收協程和SN-傳送協程。其中SN-接收協程負責接收來自客戶端的操作請求; SN-傳送協程負責將傳送操作應答給客戶端。

2.2 接收客戶端請求

SN-接收協程用於接收來自客戶端的請求。如果命令型別是QUIT、AUTH、SELECT、PING時, 則不用再轉發到後端服務。如果是MGET、MSET、DEL這種支援同時操作多個鍵的命令,則需要將該命令按照操作鍵的個數N拆散成N個操作,再分發到不同的後端傳送佇列,某請求每分發一次,其等待計數加1。再將整個操作請求放入tasks佇列,交給SN-傳送協程等待應答完成。
這裡寫圖片描述

 

注意事項:
  1.Codis只支援通過select選擇0分割槽,選擇其他分割槽均會報錯。
  2.如果pipeline中的命令個數超過tasks佇列的長度,可能會出現執行結果較長時間未返回的現象。
  3.某請求每分發一次,其等待計數加1。

2.3 應答客戶端請求

SN-傳送協程用於將請求處理結果傳送給客戶端。SN-傳送協程首先從tasks中獲取到客戶端提交的操作請求,之後直接阻塞等待應答,直到等待計數減為0時,則認為該請求的應答全部收到,再合併應答結果,並最終傳送結果給客戶端。
這裡寫圖片描述

2.4 客戶端請求分發

請求分發的目的是將操作請求傳送到正確的codis-server服務。
這裡寫圖片描述

 

注意事項:
  1.通過crc32(KEY)%1024計算被操作的KEY屬於哪個slot物件。
  2.如果正要被操作的KEY屬於被遷移的slot物件,則在放入bc.input佇列前,codis-proxy會給對應的codis-server傳送遷移某KEY的指令,並阻塞等待遷移的結果。如果遷移成功,則再將本次的操作請求放入對應的bc.input佇列; 如果遷移失敗,則返回錯誤給客戶端。

2.5 轉發請求至後端

BC-傳送協程的主要職責是將bc.input佇列中的資料傳送到某codis-server服務。
這裡寫圖片描述

2.6 接收後端的應答

BC-接收協程的主要職責接收來自某codis-server的應答資料。每完成一次應答的接收,BC-接收協程就會發送應答完成訊號,以此告知SN-傳送協程完成一次應答接收。
這裡寫圖片描述

 

注意事項:
  1.SN-傳送協程每收到一次應答完成訊號,其等待次數將會減1。如果等待次數減為0時,SN-傳送協程則認為所有應答都已收到,可進行後續處理。

2.7 處理來自ZK事件

Codis使用zk儲存各結點的狀態,各結點通過zk的訂閱功能感知各結點狀態的變化並作出相應的處理,以此達到增強叢集擴充套件性和叢集容災性的目的。
這裡寫圖片描述

3 注意事項

3.1 配置相關

 

配置欄位: session_max_timeout
  作用說明:當客戶端與PROXY之間的連線超過此時間未傳送有效操作命令時,PROXY端將主動關閉此連線。
  問題描述:將此值配置為非0時,可能出現的客戶端進行REDIS操作時出現EOF的錯誤。
  問題原因:由於很多客戶端SDK使用的是同步等待Redis請求應答的機制,而非事件觸發機制管理與PROXY端的連線。這就出現PROXY端主動關閉連線後,客戶端並未感知關閉事件。待客戶端從連線池獲取的連線時,可能獲取的連線物件實際已被PROXY端關閉,致使客戶端進行REDIS操作時出現EOF的錯誤。
  解決方案:將此值設定為0,即:PROXY端永遠不超時。例如:codis後續版本reborn就已經取消了此值的配置。


 

配置欄位: session_max_pipeline
  作用說明:用於指定每次提交的PIPELINE中命令最大數。
  問題描述:如果某此提交的PIPELINE中命令數超過此值,將可能導致PROXY發生阻塞,故客戶端也因此而阻塞。
  問題原因:由於SN-接收協程會將PIPELINE中的請求拆分成N個命令,並依次放入tasks佇列中。而tasks佇列的長度與session_max_pipeline一致。
  解決方案: 1. 控制客戶端提交的各PIPELINE中命令個數 2. 適當增大該值。

3.2 其他事項

 

問題描述:客戶端與PROXY端通訊時,必須全部接收來自PROXY端的資料。特別是PIPELINE操作時一定需要遵守此原則。否則可能出現PROXY程序“偶爾”異常退出,而zk報的異常卻是:”session expired”。
  解決方案:嚴格遵循“必須接收所有請求的應答”


 

問題描述:可通過控制域名的方式,使zk管理多個codis叢集。但是codis-proxy、codis-server、codis-cconfig、codis-ha等無法複用。即:codis叢集只可以複用zk叢集。

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述