在前文《利用redis-sentinel+keepalived实现redis高可用》详细描述了利用redis-sentinel+keepalived实现redis高可用的方案。本文中redis-sentinel的应用场景也是一样的,也是提供Redis单实例服务,当某Redis(master)服务意外停掉或该服务所在的主机发生宕机故障或网络故障时,另一台Redis服务会由slave自动成为master,提供Redis读写服务。redis-sentinel的配置可以参考前文,本文略去,只讨论consul代替keepalived。
由于keepalived的应用场景有限,比如它的核心协议VRRP只能工作在局域网内,不能工作在局域网外(网间、广域网),而且在网络不受自己控制时基本不能用,除非设定好的VIP是供局域网使用。因此特别是在云计算环境中,使用云主机(例如阿里云ECS等)就不能用keepalived,因此只能寻找一个可替代keepalived的解决方案来替代它。Consul作为服务注册、服务发现的最佳选择,无疑可以很好的替代keepalived。
前文是用的keepalived提供一个VIP为上层应用提供访问入口,本文是将keepalived替换成consul,利用consul的DNS Interface为上层应用提供Redis(master)的IP。
前提条件:需要一个可用的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找到,如下图所示。
例如用redis-cli测试一下Redis集群。
文中只是利用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