基于内存的Redis应该是各种Web开发服务中最常用的键值数据库。我们经常使用它来存储业务中的用户登录状态(会话存储)以加速一些热数据查询(与mysql相比)。速度有一个数量级的改进),做简单的消息队列(LPUSH和BRPOP),订阅发布(PUB/SUB)系统等。较大的互联网公司通常拥有专门的团队,提供Redis存储作为个人业务呼叫的基本服务。
但是,呼叫者会询问任何基本服务提供商:您的服务是否高度可用?最好不要在我的服务中造成问题,导致我的业务受损。最近,我还在项目中设置了一个小的“高可用性”Redis服务,我将自己总结和思考。
首先,我们必须定义Redis服务的高可用性,也就是说,在各种异常的情况下,仍然可以正常提供服务。或者更宽松,如果出现异常,只能在短时间内恢复正常服务。所谓的异常应至少包含以下几种可能性:
[例外1]节点服务器的某个进程突然停止(例如,开发缺陷,杀死服务器的redis-server进程)
[例外2]节点服务器已关闭,这意味着此节点上的所有进程都已停止(例如,禁用了操作和维护,并且拔出了一台服务器的电源;例如,某些旧计算机出现硬件故障)
[例外3]任何两个节点服务器之间的通信中断(例如,临时工作者被禁用,并且用于两个房间之间通信的光缆被破坏)
实际上,上述任何一个例外都是小概率事件,高可用性的基本指导原则是可以忽略同时发生的多个小概率事件的概率。只要我们设计的系统能够在短时间内容忍单点故障,就可以实现高可用性。
Internet上有许多选项可用于构建高可用性Redis服务,例如Keepalived,Codis,Twemproxy和Redis Sentinel。 Codis和Twemproxy主要用于大型Redis集群,也是Twitter和Pea pods在Redis正式发布Redis Sentinel之前提供的开源解决方案。我的业务中的数据量并不大,因此群集服务会浪费机器。最后在Keepalived和Redis Sentinel之间做出选择,选择官方解决方案Redis Sentinel。Redis Sentinel可以理解为监视Redis Server服务是否正常的进程,一旦检测到异常,它就可以自动启用Redis服务器备份,以便外部用户不会意识到Redis服务中的异常。我们以简单而复杂的方式构建了一个最低限度的高可用性Redis服务。
选项1:独立的Redis服务器,没有Sentinel
通常,当我们访问个人网站或进行开发时,我们将启动Redis Server的单个实例。调用者可以直接连接到Redis服务,甚至客户端和Redis本身也在同一台服务器上。这种搭配仅适合个人学习和娱乐。毕竟,此配置中始终存在单点故障。一旦Redis服务进程挂起,或者服务器1出现故障,该服务就不可用。如果未配置Redis数据持久性,则已存储在Redis中的数据也将丢失。
场景2:主从同步Redis Server,单实例Sentinel
为了实现高可用性,解决方案1中描述的单点故障问题,我们必须添加备份服务,即在两台服务器中的每一台上启动Redis Server进程。通常,服务由主服务器提供,从服务器仅负责同步。并备份。同时,启动额外的Sentinel进程以监视两个Redis Server实例的可用性,以便在主服务器挂起时,从服务器被提升为主服务器的角色以继续提供服务,从而实现服务器的高可用性。 Redis服务器。这是基于高可用性服务的设计,即单点故障本身是一个小概率事件,并且多个单点同时故障(即主站和从站同时挂起)可以被认为是(基本的) )不可能的事件。
对于Redis服务的调用者,它现在连接到Redis Sentinel服务,而不是Redis服务器。一个常见的调用过程是客户端首先连接到Redis Sentinel并询问Redis Server中哪个服务是主服务器,哪个服务是从服务器,然后连接到相应的Redis服务器进行操作。当然,目前的第三方库通常都实现了这个调用过程,我们不再需要手动实现它们(例如ioreis for Nodejs,predis for PHP,go-redis/redis for Golang,jedis for JAVA等。 )。但是,在实现Redis Server服务的主从切换后,我们引入了一个新问题,即Redis Sentinel本身也是一个单点服务。 Sentinel进程挂起后,客户端无法链接Sentinel。因此,选项2的配置无法实现高可用性。