1.概述
分布式系統緩存已經變得不可或缺,本文主要闡述如何實現redis主從復制集群的負載均衡,以及 redis的"高可用"實現, 呵呵雙引號的"高可用"並不是傳統意義的高可用哈,而是 redis集群掛了,並不影響asp.net core 的運行, 欲知詳情,請看下文.
注意: 本文主要闡述redis 的復制均衡和"高可用", 故redis 的主從復制搭建略, 請自行百度.
2.負載均衡實現
目前在tcp 負載均衡這塊, haproxy 是官方實現, nginx 是三方實現, 個人偏向haproxy的簡單易用. 故redis的負載均衡采用haproxy實現.
Haproxy配置文件如下:
global log 127.0.0.1 local2 #log語法:log <address_1>[max_level_1] # 全局的日志配置,使用log關鍵字,指定使用127.0.0.1 上的syslog服務中的local0日志設備,記錄日志等級為info的日志 chroot /var/lib/haproxy #當前工作目錄 pidfile /var/run/haproxy.pid #當前進程id文件 maxconn 6000 #最大並發連接數 user haproxy #所屬用戶 group haproxy #所屬組 daemon #以守護進程方式運行haproxy stats socket /var/lib/haproxy/stats defaults mode http #默認的模式mode { tcp|http|health },tcp是4層,http是7層,health只會返回OK log global #應用全局的日志配置 option httplog #啟用日志記錄HTTP請求,默認haproxy日志記錄是不記錄HTTP請求日志 option dontlognull # 啟用該項,日志中將不會記錄空連接。所謂空連接就是在上游的負載均衡器或者監控系統為了探測該 服務是否存活可用時,需要定期的連接或者獲取某一固定的組件或頁面,或者探測掃描端口是否在監聽或開放等動作被稱為空連接;官方文檔中標注,如果該服務上游沒有其他的負載均衡器的話,建議不要使用該參數,因為互聯網上的惡意掃描或其他動作就不會被記錄下來 option http-server-close #每次請求完畢后主動關閉http通道 option forwardfor except 127.0.0.0/8 #如果服務器上的應用程序想記錄發起請求的客戶端的IP地址,需要在HAProxy上 配置此選項, 這樣 HAProxy會把客戶端的IP信息發送給服務器,在HTTP請求中添加"X-Forwarded-For"字段。 啟用 X-Forwarded-For,在requests頭部插入客戶端IP發送給后端的server,使后端server獲取到客戶端的真實IP。 option redispatch # 當使用了cookie時,haproxy將會將其請求的后端服務器的serverID插入到cookie中,以保證會話的SESSION持久性;而此時,如果后端的服務器宕掉了, 但是客戶端的cookie是不會刷新的,如果設置此參數,將會將客戶的請求強制定向到另外一個后端server上,以保證服務的正常。 retries 3 # 定義連接后端服務器的失敗重連次數,連接失敗次數超過此值后將會將對應后端服務器標記為不可用 timeout http-request 10s #http請求超時時間 timeout queue 1m #一個請求在隊列里的超時時間 timeout connect 10s #連接超時 timeout client 1m #客戶端超時 timeout server 1m #服務器端超時 timeout http-keep-alive 10s #設置http-keep-alive的超時時間 timeout check 10s #檢測超時 maxconn 6000 #每個進程可用的最大連接數 listen stats #統計界面 mode http bind *:2080 stats enable stats refresh 30s stats uri /hastats stats realm Haproxy\ Statistics stats auth admin:admin stats admin if TRUE frontend healthcheck bind :1099 #定義外部檢測機制 mode http #http 負載均衡 option httpclose option forwardfor default_backend AnuoApcNodes frontend http-in bind *:88 #監聽的端口,處理請求的服務器集群為 default_backend 的配置值 mode http log global option httpclose option logasap #不等待響應結束就記錄日志,表示提前記錄日志,一般日志會記錄響應時長,此不記錄響應時長 option dontlognull #不記錄空信息 capture request header Host len 20 #記錄請求首部的前20個字符 capture request header Referer len 60 #referer跳轉引用,就是上一級 default_backend AnuoApcNodes #處理請求的服務器集群 backend AnuoApcNodes #處理請求的服務器集群 mode http balance roundrobin #check : 下面的check 表示ha 需要檢查此節點的狀態 server websrv1 192.168.2.108:9090 check maxconn 6000 server websrv2 192.168.1.112:88 check maxconn 6000 listen SQLServer :1433 #tcp 負載均衡 mode tcp balance roundrobin #weight : 權重, 表示此節點的優先級,值越高(最高256) , 優先執行越高 #check port : 檢測是否存活的端口 #inter : interval 檢測是否存活的 時間間隔 #rise : server 從離線狀態轉為正常狀態后, 需要復查的次數(看是否正常) #fall : server 從正常狀態轉換為不可用狀態需要檢查的次數 server SQLServer1 192.168.2.101:1433 weight 1 maxconn 6000 check port 1433 inter 2000 rise 2 fall 2 server SQLServer2 192.168.2.203:1433 weight 1 maxconn 6000 check port 1433 inter 2000 rise 2 fall 2 listen Redis :6377 #tcp 負載均衡 mode tcp balance roundrobin #weight : 權重, 表示此節點的優先級,值越高(最高256) , 優先執行越高 #check port : 檢測是否存活的端口 #inter : interval 檢測是否存活的 時間間隔 #rise : server 從離線狀態轉為正常狀態后, 需要復查的次數(看是否正常) #fall : server 從正常狀態轉換為不可用狀態需要檢查的次數 server Redis1 192.168.2.101:6379 weight 1 maxconn 6000 check port 6379 inter 2000 rise 2 fall 2 server Redis2 192.168.2.102:6379 weight 1 maxconn 6000 check port 6379 inter 2000 rise 2 fall 2
其中最后的配置:
為redis的負載均衡配置, 可以看到負載了兩個redis IP, 101和102 .
在實際運行中, redis的主庫一般用作寫, 從庫用作讀, so , 一般針對redis的從庫進行負載.
只需將上面的兩個IP 替換為自己的ip 即可完成對 redis 從庫的負載.
3. asp.net core 端針對 redis "高可用"實現
實現思路: 此處的實現不是傳統意義的高可用實現,而是C#端檢測到redis集群掛了, 自動將redis從系統中剔除, 保證asp.net core 能繼續運行
業界問題: redis 的高可用有官方實現叫sentinel , 現在應用案例並不多, 也逮到官方文檔看了哈, 看了半天沒看到, 有sentinel實戰教程推薦的,或其他高可用實現的, 望留言 ^_^
先下載完整源碼: http://pan.baidu.com/s/1i52ViWP
源碼配置運行步驟如下:
如下圖
3.1.配置VIPPort的值為 haproxy 暴露的redis 集群端口,如下圖值
3.2.配置ClusterVIPCom值為 haproxy 所在服務器 的 IP
3.3.配置ClusterMultiIPCom 值為 redis主從復制集群中的全部從庫IP, 用分號分割IP
3.4. 代碼運行起來, 調用 Sample 接口, 如下圖
調用URL: Get方法 http://localhost:9526/api/RedisTest/Sample
運行邏輯如下:
第一次取數據, redis沒得緩存, 制造緩存對象, 緩存到redis, 成功返回.
第二次取數據, redis 有緩存, 從緩存中取, 成功返回.
第三次取數據, 假如redis掛了, 制造緩存對象, 還是成功返回.
第四次取數據, redis恢復了, 重啟 asp.net core , 程序自動連接上redis, 從redis返回數據, 成功返回.
至此達到了, redis 和 asp.net core 的完全解耦, 即redis掛了不影響 asp.net core 的繼續運行 .
可以想象哈, 當你半夜收到一個警報說redis掛了的時候, 你可以不慌不忙的去公司慢慢改, 因為asp.net core 還在運行, 只是慢了點而已.