【0】代理功能與性能對比
目前市面上主流的代理包含:predixy、twemproxy、codis、redis-cerberus四款,這四款各有各的優勢,我們逐個對比進行對比分析。

如上圖,我們發現 twemproxy / codis 都不支持 redis-cluster,所以我們放棄使用;(但業界 codis 用的挺多的)
性能測試報告 2017:https://blog.csdn.net/rebaic/article/details/76384028
性能測試測試報告 2020:https://github.com/netease-im/camellia/blob/master/docs/redis-proxy/performance-report-8.md
redis架構發展:https://www.cnblogs.com/crazymakercircle/p/14282108.html
【1】predixy的安裝和配置
【1.1】基本介紹
predixy 是高性能的適用於 redis 集群和哨兵的代理。
predixy github 地址:https://github.com/joyieldInc/predixy
predixy 編譯安裝需要 C++11 版本的編譯器,至少需要 CentOS 7及以上版本才能編譯安裝。
對於 CentOS 6或更低版本,可以直接使用在 github release 中的二進制版本。
【1.2】特性、優點
- 同並輕量級
- 支持多線程
- 多平台支持:Linux、OSX、BSD、Windows( Cygwin )
- 支持Redis Sentinel,可配置一組或者多組redis
- 支持Redis集群
- 支持redis多種類型的命令,包括blpop、brpop、brpoplpush
- 支持掃描命令,無論是單個redis還是多個redis實例都支持
- 多鍵命令支持:mset/msetnx/mget/del/unlink/touch/exists
- 支持redis的多數據庫,即可以使用select命令
- 支持事務,當前驗證於Redis Sentinel下組redis組可用
- 支持腳本,包括命令:script load、eval、evalsha
- 支持發布訂閱機制,也即Pub/Sub系列命令
- 多數據中心支持,刪除支持
- 擴展的AUTH命令,部分的讀、寫、管理權限控制機制,健空間限制機制
- 日志可按級別輸出,記錄日志被io實時記錄
- 日志文件可以按時間、大小自動切分
- 大量的統計信息,包括CPU、內存、請求、響應等信息
- 延遲監控信息,可以看到整體延遲,分秒還原事件延遲
【2】安裝
【2.1】下載解壓
tar -xzf predixy-1.0.5-bin-amd64-linux.tar.gz
mv predixy-1.0.5 /data/redis/
cd /data/redis/predixy-1.0.5/conf/
【2.2】修改配置文件 cluster.conf
配置文件官方說明:https://github.com/joyieldInc/predixy/blob/master/doc/config_CN.md
predixy 支持多種架構,由於使用的是 redis cluster,只需配置 redis cluster 對應的配置文件cluster.conf 即可。
內容如下:
##ClusterServerPool {
## [Password xxx] #default no
## [MasterReadPriority [0-100]] #default 50
## [StaticSlaveReadPriority [0-100]] #default 0
## [DynamicSlaveReadPriority [0-100]] #default 0
## [RefreshInterval number[s|ms|us]] #default 1, means 1 second
## [ServerTimeout number[s|ms|us]] #default 0, server connection socket read/write timeout
## [ServerFailureLimit number] #default 10
## [ServerRetryTimeout number[s|ms|us]] #default 1
## [KeepAlive seconds] #default 0, server connection tcp keepalive
# Examples:
ClusterServerPool {
Password 123456
MasterReadPriority 60
StaticSlaveReadPriority 50
DynamicSlaveReadPriority 50
RefreshInterval 1
ServerTimeout 1
ServerFailureLimit 10
ServerRetryTimeout 1
KeepAlive 120
Servers {
+ 192.168.191.176:6381
+ 192.168.191.176:6382
+ 192.168.191.211:6383
+ 192.168.191.211:6384
+ 192.168.191.70:6385
+ 192.168.191.70:6386
}
}
參數說明:
MasterReadPriority,StaticSlaveReadPriority,DynamicSlaveReadPriority 三個參數和 redis 本身配置文件中的 slave-priority 沒任何關系的。
如果是自動發現找到的節點,則 DynamicSlaveReadPriority 會起作用,如果是直接配置的節點,則 StaticSlaveReadPriority 會起作用。
Master/SlaveReadPriority |
Master |
Slave1 |
Slave2 |
Fail-over notes |
60/50 |
all requests |
0 requests |
0 requests |
Master dead, read requests deliver to slave until master(maybe new master) alive |
60/0 |
all requests |
0 requests |
0 requests |
Master dead, all requests fail |
50/50 |
all write requests, 33.33%read requests |
33.33% read requests |
33.33% read requests |
- |
0/50 |
all write requests, 0 read requests |
50% read requests |
50% read requests |
all slaves dead, all read requests fail |
10/50 |
all write requests, 0 read requests |
50% read requests |
50% read requests |
all slaves dead, read requests deliver to master |
RefreshInterval : predixy 獲取節點信息和集群 hash slot 集群信息的間隔
ServerFailureLimit : predixy 停止路由到節點之前失敗的次數
ServerTimeout : 單個命令執行的超時時間
Password: 指定連接redis實例默認的密碼,不指定的情況下表示redis不需要密碼
【2.3】集群自動發現
在 Servers 部分配置集群中任意一個節點即可,predixy 會自動發現整個集群的信息,即使配置的節點掛掉后,predixy 代理仍然可正常工作。
通過自動發現集群,可以減少 cluster.conf 配置文件的修改及對 predixy 的重啟操作。
但 predixy 無法刪除曾經自動發現的節點,如果某節點下掉,predixy 仍會看到之前的節點,雖然不影響正常使用,日志則會不斷報出錯誤信息。需重啟 predixy 解決。
【2.4】配置 predixy.conf
Name Predixy001
Bind 0.0.0.0:7617
WorkerThreads 4
ClientTimeout 300
Log /data/redis/predixy-1.0.5/predixy.log
LogRotate 1d
LogRotate 200M
Include cluster.conf
注意 Include 部分,只需包括 cluster.conf,其他的則注釋掉,否則可能會影響到 predixy的使用。
基本配置文件說明:
- predixy.conf,整體配置文件,會引用下面的配置文件
- cluster.conf,用於Redis Cluster時,配置后端redis信息
- sentinel.conf,用於Redis Sentinel時,配置后端redis信息
- auth.conf,代理中心訪問權限控制配置,可以定義多個驗證密碼,可每個密碼指定讀、寫、管理權限,以及定義可訪問的健空間
- dc.conf,多數據中心支持,可以定義讀寫分離規則,讀流量權重分配
- latency.conf, 延遲監控規則定義,可以指定需要監控的命令以及延時時間間隔
- command.conf,自定義命令擴展,用於命令擴展,支持redis 的插件以及自定義數據處理函數等
- standalone.conf,使用單擊模式的redis配置
【2.5】啟動predixy
cd /data/redis/predixy-1.0.5/bin/
cp predixy /data/redis/bin/ #我的redis 啟動命令在這里,已添加進環境比那里
啟動
看情況任選一即可
nohup predixy /data/redis/predixy-1.0.5/conf/predixy.conf &
nohup predixy /data/redis/predixy-1.0.5/conf/predixy.conf >/data/redis/predixy-1.0.5/predixy.log 2>&1 &
查看日志
tail -f /data/redis/predixy-1.0.5/predixy.log
如上,我們可以看到,由於配置文件 predixy.conf 配置的確是啟動了4個進程,所以我們4個線程都就緒連接到集群所有機器了;對應構建連接池
predixy 添加環境變量
在 /etc/profile 中添加,然后在 /etc/rc.local 中設置開機啟動 ,任選一即可
echo 'nohup predixy /data/redis/predixy-1.0.5/conf/predixy.conf &' >> /etc/rc.local
nohup predixy /usr/local/predixy-1.0.5/conf/predixy.conf > /data/redis/predixy-1.0.5/predixy.log 2>&1 &
【3】連接核驗
代理連接,直接連 7617 端口就行
redis-cli -p 7617 info
可以看到 mget mset 都是沒有問題的
同時代理日志信息如下:
我們通過集群的方式連接,發現key 什么的確實過去了
【4】故障轉移測試
【4.1】關閉一個主庫
redis-cli -h 192.168.191.70 -p 6385 -a 123456 shutdown
tail -f /data/redis/predixy-1.0.5/predixy.log
我們可以發現,b2 之前是在 6385
故障轉移之后,6382 從庫,經過故障轉移接替 6385 成為主庫;
我們繼續連接代理查詢:
如上圖,安穩查詢那么,證明故障轉移是可以的;程序連接的代理,不會感知到任何東西;
同時我們查看代理日志:
看這,和炸街了一樣,一直報;
這就如同【2.3】說的
在 Servers 部分配置集群中任意一個節點即可,predixy 會自動發現整個集群的信息,即使配置的節點掛掉后,predixy 代理仍然可正常工作。
通過自動發現集群,可以減少 cluster.conf 配置文件的修改及對 predixy 的重啟操作。
但 predixy 無法刪除曾經自動發現的節點,如果某節點下掉,predixy 仍會看到之前的節點,雖然不影響正常使用,日志則會不斷報出錯誤信息。需重啟 predixy 解決。
我們連接代理,在 info 中可以發現:
該配置信息依然在,但其狀態 CurrentIsFail:1
總結:
代理可用,集群正常故障轉移,程序無感;
運維問題:日志會一直報錯;forget 也沒用
【4.2】下掉一個從節點
我們下一個從節點看看;
我們下掉6383吧;
redis-cli -h 192.168.191.211 -p 6383 -a 123456 shutdown
查看代理日志:
會一直報錯,連不上6383,直到去掉配置文件中的這個實例,重啟代理
總結:
代理可用,集群正常故障轉移,程序無感;
運維問題:日志會一直報錯;forget 也沒用
【4.3】關閉沒有從庫的主庫(徹底關閉一對主從)
我們關閉 6386和6383這對主從吧,看看代理這時候會發生什么;
redis-cli -h 192.168.191.211 -p 6383 -a 123456 shutdown
redis-cli -h 192.168.191.70 -p 6386 -a 123456 shutdown
我們可以看到,現在redis-cluster 已經有問題了;
我們看看代理操作是什么情況;
我們發現是不能訪問的!
集群參數:
集群參數也是沒一個開的;
【4.4】代理下的集群參數測試,非全slot 可用性
我們這里就不測那么多了,測一個即可,節點先啟動回去
然后我們測試 cluster-allow-reads-when-down yes 這個參數吧
redis-cli -h 192.168.191.176 -p 6381 -a 123456 config set cluster-allow-reads-when-down yes
redis-cli -h 192.168.191.176 -p 6382 -a 123456 config set cluster-allow-reads-when-down yes
redis-cli -h 192.168.191.211 -p 6383 -a 123456 config set cluster-allow-reads-when-down yes
redis-cli -h 192.168.191.211 -p 6384 -a 123456 config set cluster-allow-reads-when-down yes
redis-cli -h 192.168.191.70 -p 6385 -a 123456 config set cluster-allow-reads-when-down yes
redis-cli -h 192.168.191.70 -p 6386 -a 123456 config set cluster-allow-reads-when-down yes
然后繼續關閉 6383 6386 一對主從的實例
redis-cli -h 192.168.191.211 -p 6383 -a 123456 shutdown
redis-cli -h 192.168.191.70 -p 6386 -a 123456 shutdown
然后我們看看代理,是否可以如之前測試那樣,對現有key 是可以訪問的;
我們發現,確實是這樣; 直連集群也是如此;
我們上主庫實例上去把開關打開;僅剩的 2個 主庫 全都開啟這個參數;
直接連redis-cluster集群上穩穩的是可以set 了; 如下圖:
代理上也可以了 對現有 存在的 slot 的操作、不存在的key 也可以創建了;如下圖:
代理日志,一直報,這是常態了,如下圖
【5】集群水平擴展、收縮測試
【5.1】新增主節點
(1)新增 6387 主節點
redis-cli --cluster add-node 192.168.191.82:6387 192.168.191.176:6381 -a 123456
(2)自動平衡分配slot 給新空主節點 6387
redis-cli --cluster rebalance --cluster-use-empty-masters 192.168.191.176:6381 -a 123456
(3)check 一下看看現在的集群信息
(4)檢查代理日志
如下圖:
我們可以發現,新加入的主節點已經被自動發現且識別出來了;
(5)使用代理操作、查閱驗證
我們用代理 mset 一下
如下圖,我們連接redis-cluster 查閱驗證,可以發現新的 key 的get set 已經完成,並且新的key 也分配到了 新加的主庫 6387
如下圖,我們連接代理,使用Info 查看也可以看到該主庫了,由於代理開了4個線程,所以現在的連接數是4,且如果線程不掛,一般會一直保持 connections為4的;
(6)結論
沒有任何問題啊,就真如redis-cluster 一樣
【5.2】新增從節點
redis-cli --cluster add-node 192.168.191.82:6388 192.168.191.176:6381 --cluster-slave -a 123456
如下圖:加入成功
如下圖:我們可以看到,代理自動識別出來了新的,木有問題啊
要是掛掉它,我們可以發現,代理的日志依然是會一直報,這表示只要有節點加入進來了,不管你是forget 還是 del-node,也不管你是否是 cluster.conf 文件中配置的集群ip;
反正只要是集群自動發現加入過的,它都會報;如果要去掉,只能重啟代理
【5.3】刪除一主一從,縮容
先刪除從庫:
redis-cli --cluster del-node 192.168.191.176:6381 45a9ea5062479aaad68b6a9c4b5cc1942639dcb4 -a 123456
再刪主庫:
(1)遷移被刪除主庫上的 slot
把槽位平均非給其他主節點
redis-cli -a 123456 --cluster rebalance --cluster-weight \
11ac5cf5004f22a55ee0afa2b221d120ad768f7d=1 f5dc23c602b57f6b09b4909d01289ff4d80220ed=1 \
4ba0958a0c9aa944962182673058fbc4c27952eb=1 4dfde05a131e9b8900553ef03ef41703737e449f=0 \
192.168.191.176:6381
(2)把節點從群集中移除,刪除主節點
redis-cli -a 123456 --cluster del-node 192.168.191.176:6381 4dfde05a131e9b8900553ef03ef41703737e449f
(3)查看代理:
查看代理日志,如下圖:
發現,居然沒有報錯(刪除節點,但節點實例未關閉,所以它並沒有報錯,依然會連接該實例)
代理查看:
發現這2個都還在,這證明了,代理不會自動更新集群狀態的刪除信息,它只會自動更新新增的集群節點信息;
關閉這 6387 6388 實例;
我們發現,連不上又報錯了;
【5.4】代理因為刪除節點報錯問題解決:重啟代理
關閉:kill 進程
自動:predixy /data/redis/predixy-1.0.5/conf/predixy.conf &
重啟后,報錯信息沒了;
登錄代理:info 中的信息也更新了
6387 和 6388 實例就不見了;恢復正常;
【6】讀寫分離與讀負載均衡的測試
Master/SlaveReadPriority |
Master |
Slave1 |
Slave2 |
Fail-over notes |
60/50 |
all requests |
0 requests |
0 requests |
Master dead, read requests deliver to slave until master(maybe new master) alive |
60/0 |
all requests |
0 requests |
0 requests |
Master dead, all requests fail |
50/50 |
all write requests, 33.33%read requests |
33.33% read requests |
33.33% read requests |
Master dead,read requests deliver to slave |
0/50 |
all write requests, 0 read requests |
50% read requests |
50% read requests |
all slaves dead, all read requests fail |
10/50 |
all write requests, 0 read requests |
50% read requests |
50% read requests |
all slaves dead, read requests deliver to master |
如下:我們現在的架構是
6382=>6385 ,6384=>6381 ,6386=>6383
【6.1】60/50 Master/SlaveReadPriority
現在的架構是:
6382=>6385 ,6384=>6381 ,6386=>6383
6350中,只有Ping
如上圖,我們發現,發送了5次 a,5次 a 全在主庫 6382;所以證明我們之前 60/50 的結論是正確的;
那么我們之前全是這種模式,就不做故障轉移測試了,可以直接得出結論了;
結論:
所有的請求,都會發送給主庫;
當主庫宕機,故障轉移期間,讀操作會發送給從庫;(也會嘗試連接主庫,連幾次無果到閾值后讀請求發送到從庫)
新主庫產生后,所有的請求發給新主庫;
【6.2】60/0 Master/SlaveReadPriority
修改 cluster.conf 參數
MasterReadPriority 60
StaticSlaveReadPriority 0
DynamicSlaveReadPriority 0
重啟:
現在的架構是:
6382=>6385 ,6384=>6381 ,6386=>6383
關閉 6382主庫:
redis-cli -h 192.168.191.176 -p 6382 -a 123456 shutdown
如下:
我們發現故障轉移期間,無法訪問 a;等故障轉移完畢,從庫變成主庫,就可以訪問了;
結論:
所有的請求,都會發送給主庫;
當主庫宕機,故障轉移期間,所有請求都會失敗;
新主庫產生后,所有的請求發給新主庫;
【6.3】50/50
現在的架構是:
6382=>6385 ,6384=>6381 ,6386=>6383
如上面3個圖,我們發現真的 50 50 讀負載均衡了;
關閉 6382主庫:
redis-cli -h 192.168.191.176 -p 6382 -a 123456 shutdown
如上圖,我們可以發現,關閉 6382 主庫之后,沒有任何影響,之前在故障轉移切換瞬間失敗了一次;
如下圖,關閉 6382 ,命令一發起它就收不到任何請求了;
如下圖:6385實例的監控,我們發現主庫掛了,從庫還沒有故障轉移切換成主庫時,read操作依然請求過來了;
結論:
讀請求平均分發給所有的主從;
當主庫宕機,故障轉移期間,讀請求都會平均分配到剩余存活的slave;
新主庫產生后,讀請求平均分發給所有的主從;
后面2個就不測了,知道它有效就行,先這樣;