目前的想法是想做DB类服务的高可用(如redis):
原理:前端应用通过SLB VIP访问redis,SLB后端配置一个redis master和若干redis slave,SLB初始配置master权重100,所有slave的权重配置为0(即只有master提供读写服务)
在redis主挂掉后,将某个slave提升为master,此时通过SLB的API将新master的权重调整为100,并将原master的权重调整为0
但是这里存在一个问题:
如果应用使用长连接连接到redis,那么我们调整SLB的访问权重并不会对这些已有的链接造成影响(特别是master短时间内又恢复的场景),即可能导致一部分已有的链接还是连接在原来的master上,更致命的是,此时的SLB的健康检查是OK的(因为此时原master只是无法写入,但是是可以telnet通的),因此应用侧会报无法写入的错误,而SLB还是将请求转发到原master,
目前想到的解决办法就是:
在slave提升为master之后,直接将原master关闭,或者将原master上的所有连接都kill掉,强制让应用侧进行断线重连,但是貌似不够优雅
PS:不要说让我使用阿里云的RDS for redis之类的,目前我们都是自建的,暂时不会使用这个,所以,小伙伴们有什么好的解决方法吗?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
面对您描述的场景,确实存在挑战,尤其是当涉及到长连接和主备切换时。不过,有几个策略可以提高这种自建Redis高可用架构的优雅性和稳定性:
客户端重定向支持:确保您的Redis客户端支持Redis的REPLICAOF
命令或者能够理解MOVED/ASK重定向响应。这样,在Redis主节点故障后,新提升的主节点可以通过Redis协议通知客户端新的写入地址,客户端可以根据提示自动重连到新的主节点。这需要客户端逻辑的支持。
代理层实现智能路由:在应用与Redis之间部署一层代理服务(如ProxySQL for MySQL或Twemproxy对于Redis),该代理负责维护当前的主从关系,并根据实时状态智能地将请求路由到正确的Redis实例。当发生主备切换时,代理层可以立即调整路由规则,而无需更改SLB配置或断开现有连接。
利用Redis Sentinel:虽然您提到不直接使用阿里云的托管服务,但Redis自带的Sentinel系统是专为高可用设计的监控和故障转移工具。它能自动发现故障并进行主备切换,同时通过发布订阅模式通知客户端主节点的变化,促使客户端重新连接到新的主节点。这种方式比直接操作SLB权重更自动化且健壮。
改进健康检查机制:如果坚持使用SLB,可以考虑优化SLB的健康检查逻辑,不仅仅检查连接是否可达,还要包括简单的读写测试,确保被转发到的Redis实例是真正可写的。这样,在主节点变为只读状态时,SLB能更快识别并停止向其转发写请求。
Graceful Shutdown & Failover Notification:在手动或通过脚本执行主备切换时,除了调整权重外,还可以尝试在原master上执行一个graceful shutdown过程,比如设置一个标志位,让正在处理的请求完成后再关闭服务,同时通过某种方式(如消息队列、HTTP回调等)通知应用层主节点已变更,应用收到通知后主动断开旧连接并重连。
综上所述,引入中间代理层或利用Redis Sentinel可能是更为优雅和自动化的解决方案,它们能更好地处理主备切换期间的连接管理和通知问题。