本文由 简悦 SimpRead) 转码, 原文地址 mp.weixin.qq.com)
redis 速度快,可靠性高,是互联网公司的标配。它有单机、主从、哨兵、Cluster 等四种部署模式。
下面,仅从部署模式上,来说明一下它们的优缺点。
单机模式
单机模式的redis
非常简单,你只需要启动一个单一的节点就可以了,安装过程不超过 5 分钟。
通过redis-benchmark
测试简单的命令,QPS
可达到10w
以上,不得不说非常的让人惊艳了。
单机模式的问题也非常明显。缺乏高可用的机制!
假如redis
进程死了,进程就只能够穿透到底层的数据库中,对业务来说非常的危险。如果你把 redis 当作数据存储来用,情况会更加严重,甚至会丢失数据。
主从模式
所以最基本的redis
部署,都会增加一个或者多个slave
(现在叫replication
)。
当主redis
发生问题的时候,能够选取一个slave
顶上去。
非常可惜的是,这种模式和传统的 MySQL 主从一样,切换起来比较蛋疼,需要借助外部的工具,比如keepalived
等辅助进行切换,部署和维护难度直接飙升。
keepalived
是一个基于VRRP
协议来实现的高可用方案,通过 IP 漂移实现高可用。从描述上就可以看出它需要网络管理员的参与,和我们轻量级的redis
背道而驰。
哨兵模式
哨兵模式就是使用额外的进程来替换keepalived
的功能,对 redis 进程的存活性进行判断。在哨兵模式下,一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
但哨兵模式一个最大的问题,就是哨兵的数量太多,至少需要 3 个节点。
对redis
进行仲裁的时候,需要n/2+1
个节点投票才能确认,这也是分布式系统的一般做法 (quorum)。和 Zookeeper 类似,哨兵节点做成奇数个,是非常合适的。
哨兵模式可以通过sentinel monitor
配置同时检测多套集群,在集群数量适中的时候,还是比较好用的。
但哨兵模式有很多隐藏的坑,比如哨兵的启动,必须在 master 存活的情况下才能正常运行;另外,如果你的 redis 配置文件中使用RENAME
屏蔽了一些危险命令时,哨兵也不能够启动。
客户端在连接 redis 的时候,就不能再直接连接 redis 的实例,它需要从哨兵转上一圈,以便获取一些变更信息。
集群模式
集群模式可以说是这里面最优雅的方式了。你只需要部署多个对等的 redis 节点,然后使用客户端命令进行组群就可以了。
ip=192.169.0.23
./bin/redis-cli --cluster create $ip:7001 $ip:7002 $ip:7003 $ip:7004 $ip:7005 $ip:7006 --cluster-replicas 1
它对节点的要求也是比较多的,一般是采用 6 个节点,三主三从。当节点超过 10 个,它的协调性就不那么灵活了,所以单集群的存储和性能上限也很快能到达。
集群模式的一些缺点很隐蔽。它的服务端节点倒是非常稳定了,但有些命令会严重影响性能。比如mget
,pipeline
等。它们需要把请求分散到多个节点执行、再聚合。节点越多,性能越低。
在下面这篇文章中,我们详细的描述了一些比较通用的 redis 使用规范,有些就是为了规避 cluster 模式引起的一些问题。
其他方案
可以看到 redis 的这些集群模式,都不是完美的。应对小型的服务可能没有问题,如果是大型的集群和服务,这些部署方式对运维上,使用上来说,都有非常大的挑战。
使用客户端 hash 的方法,是大型互联网中常用的方式。参考下面的文章,现实中的路由规则,可能会相当复杂,但请求总能够精确的落在某个小的群组上面。
对于管理大型集群来说,我倒是倾向于主从模式,然后使用 Java 或者其他语言开发一个可以集中管控的哨兵系统,对上千个集群进行管理。
由于 Redis 是文本协议,协议非常简单,Netty 甚至直接内置了它的解析器,所以开发这么一个哨兵系统是非常简单的。
一些中间层代理软件,也能分担一些路由工作,但由于是中间层,涉及到一层网络转发,对 Redis 这种以速度取胜的服务来说,就不是很实用。
变种有更多,比如下面这篇文章,使用的是 Redis 协议,但后端存储却是 MySQL,所以你的命令会是被阉割的。
从上面的描述中我们就可以看出,Redis 能用是一回事,用好是另一回事。
你可能花了一天时间搭建了一个单节点的 Redis;我可能花了一周时间写了个 Java 版的哨兵,还有很多 BUG。这两者在不懂技术的领导眼里,是没有区别的 — 它们都满足了业务的需求。但也不必过分计较,现实一般都比较残酷,计算机系统也没有想象中的那么稳定,墨菲定律总有一个时间会教会他们做人。