標籤:redis叢集 redis-sentinel redis高可用 redis主從複製 consul api
在前文《利用redis-sentinel+keepalived實現redis高可用》詳細描述了利用redis-sentinel+keepalived實現redis高可用的方案。本文中redis-sentinel的應用情境也是一樣的,也是提供Redis單一實例服務,當某Redis(master)服務意外停掉或該服務所在的主機發生宕機故障或網路故障時,另一台Redis服務會由slave自動成為master,提供Redis讀寫服務。redis-sentinel的配置可以參考前文,本文略去,只討論consul代替keepalived。
前文是用的keepalived提供一個VIP為上層應用提供訪問入口,本文是將keepalived替換成consul,利用consul的DNS Interface為上層應用提供Redis(master)的IP。
650) this.width=650;" title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;" border="0" alt="image" src="http://s3.51cto.com/wyfs02/M01/7C/69/wKioL1bP_qWxg1v3AAD02U9fD1w015.png" height="473" />
前提條件:需要一個可用的consul叢集,可以利用consul叢集本身和設定檔註冊服務,也可以用一台單獨的主機註冊,還可以用HTTP API向Consul註冊。
為了擷取Redis(master)的IP而不是Redis(Slave)的IP,可以用指令碼檢查實現,與keepalived指令碼中相似,只是傳回值將1設定成2,因為consul中傳回值0是沒問題(passed),1是警告(warning),2是嚴重(critical)。
下面是用一台單獨的主機註冊的例子。
json設定檔如下:
{ "services": [ { "id": "redisnode1", "name": "redis", "tags": [ "master" ], "address": "192.168.1.241", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.241 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] }, { "id": "redisnode2", "name": "redis", "tags": [ "master" ], "address": "192.168.1.242", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.242 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] }, { "id": "redisnode3", "name": "redis", "tags": [ "master" ], "address": "192.168.1.243", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.243 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] } ]}
註冊是利用consul agent作為Client運行註冊的,假設consul叢集中某台Server的地址是192.168.1.245。
mkdir -p /usr/local/consul/data /usr/local/consul/config cat >/usr/local/consul/config/rediscluster.json<<eof{ "services": [ { "id": "redisnode1", "name": "redis", "tags": [ "master" ], "address": "192.168.1.241", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.241 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] }, { "id": "redisnode2", "name": "redis", "tags": [ "master" ], "address": "192.168.1.242", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.242 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] }, { "id": "redisnode3", "name": "redis", "tags": [ "master" ], "address": "192.168.1.243", "port": 6379, "checks": [ { "script": "/usr/local/sbin/redis-cli -h 192.168.1.243 -p 6379 info | grep role:master || exit 2", "interval": "5s" } ] } ]}eof/bin/consul agent -advertise=$(ifconfig $(route -n | awk ‘/^0.0.0.0/ && /UG/ {print $NF}‘) | grep inet | egrep -v "(inet6|127.0.0.1)" | cut -d ":" -f2 | cut -d " " -f1) -bind=$(ifconfig $(route -n | awk ‘/^0.0.0.0/ && /UG/ {print $NF}‘) | grep inet | egrep -v "(inet6|127.0.0.1)" | cut -d ":" -f2 | cut -d " " -f1) -data-dir=/usr/local/consul/data -config-dir=/usr/local/consul/config -join 192.168.1.245
需要後台運行時可以添加nohup thiscommandline >/path/to/logfile 2>&1 &
注意:在consul json設定檔中,每個consul agent的service id都不能重複,name是強制要求的,必須要有,如果id省略,則跟name相同,其他的都是可選的,可有可無。但為了能夠使用某條服務資訊,就必須要有IP和port,當然port可以在應用中指定。check最好要有,否則當出現問題時不能從consul中取消註冊。
注意:上述命令列中使用的是與預設閘道同網段IP(公網IP地址),要求此地址與consul叢集地址之間能互相訪問。在啟動consul agent之前可以下面兩行命令中的一行確定是否滿足此條件:
consul info -rpc-addr=192.168.1.245:8400 consul members -rpc-addr=192.168.1.245:8400
在consul agent啟動後,此時Redis的資訊就會在consul中展示出來,包括UI、DNS Interface和HTTP API中都能查詢到。使用Redis的應用應該將DNS指向consul叢集的DNS地址,這樣才能查詢到Redis服務對應的IP。
通過consul HTTP API中提供的“curl http://192.168.1.245:8500/v1/catalog/service/redis”方法只能列舉出當前service:redis中有哪些節點,但無法區分這些節點中哪些是正常工作的節點,哪些是有問題的節點,但DNS Interface方法“dig @192.168.1.245 -p 53 redis.service.dc1.consul. ANY”可以準確的將可用的節點的IP找到,如所示。
650) this.width=650;" title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;" border="0" alt="image" src="http://s3.51cto.com/wyfs02/M02/7C/6A/wKiom1bP_jeyh1swAABIwWfH6CM314.png" height="602" />
650) this.width=650;" title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;" border="0" alt="image" src="http://s3.51cto.com/wyfs02/M01/7C/6A/wKiom1bP_jjAuQ4ZAABAKMJYjFc500.png" height="342" />
例如用redis-cli測試一下Redis叢集。
650) this.width=650;" title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;" border="0" alt="image" src="http://s3.51cto.com/wyfs02/M02/7C/6A/wKiom1bP_jmDVIxWAAAOQh3SBEs816.png" height="86" />
文中只是利用consul的DNS Interface擷取到了Redis叢集的master的IP,並沒有擷取到port,儘管可以通過“dig @192.168.1.245 -p 53 redis.service.consul SRV”可以擷取到port,但對於上層應用來說並不是很好做,畢竟大部分應用的網域名稱解析是不會查詢SRV記錄的。本文的consul是Consul v0.6.0,目前有更新的版本0.6.3可以使用,https://www.consul.io/downloads.html ,consul可能還有其他比較好用的方法更好的擷取服務的IP和Port,以後使用的過程中也會再補充。更多關於consul的資訊可以參考consul的官方網站:https://www.consul.io/。
注意:可能存在的問題。如果Redis master發生故障,原先的slave會變成新的master,DNS緩衝可能不會重新整理,這個在發生故障處理時需要注意清空上層應用的DNS緩衝。
tag:Redis叢集,Redis高可用,redis-sentinel,consul API,Redis主從複製
--end--
本文出自 “通訊,我的最愛” 部落格,請務必保留此出處http://dgd2010.blog.51cto.com/1539422/1745314
利用redis-sentinel+consul實現redis高可用