前言
Redis
是一个高性能的key-value
数据库,现时越来越多企业与应用使用Redis
作为缓存服务器。楼主是一枚JAVA
后端程序员,也算是半个运维工程师了。在Linux
服务器上搭建Redis
,怎么可以不会呢?下面楼主就带着大家从0开始,依次搭建:Redis
单机服务器 -> Redis
主从复制 -> Redis-Sentinel高可用
。逐步搭建出高可用的Redis缓存服务器。主要参考文章:简书:搭建一个redis高可用系统
楼主基于此文一步步参考着搭建,所以内容较为相似,感谢原文作者,特此申明。
本文同步发布于简书 :http://www.jianshu.com/p/d7bc873b8797
搭建Redis
1. 下载并解压
首先从Redis
官网下载Redis
并解压,楼主使用的版本是4.0.2。依次执行如下命令:
1 | 复制代码cd /usr/local/ |
如果没有安装gcc
依赖包,则安装对应依赖包
1 | 复制代码yum install -y gcc-c++ tcl |
2. 编译并安装
下载并解压完毕后,则对源码包进行编译安装,楼主的Redis
安装路径为/usr/local/redis
,同学们可以自行修改语句:make install PREFIX=你想要安装的路径
1 | 复制代码cd /usr/local/redis-4.0.2/ |
复制Redis
相关命令到/usr/sbin
目录下,这样就可以直接执行这些命令,不用写全路径
1 | 复制代码cd /usr/local/redis/bin/ |
3. 建立Redis配置文件
安装完成之后将 Redis
配置文件拷贝到系统配置目录/etc/
下,redis.conf
是 Redis
的配置文件,redis.conf
在 Redis
源码目录,port
默认 6379。
1 | 复制代码cp /usr/local/redis-4.0.2/redis.conf /etc/ |
Redis
配置文件主要参数解析参考
1 | 复制代码daemonize no #redis进程是否以守护进程的方式运行,yes为是,no为否(不以守护进程的方式运行会占用一个终端) |
3.1 设置后端启动:
由于Redis
默认是前端启动,必须保持在当前的窗口中,如果使用ctrl + c
退出,那么Redis
也就退出,不建议使用。
1 | 复制代码vi /etc/redis.conf |
修改Redis
配置文件把旧值daemonize no
改为 新值daemonize yes
3.2 设置访问:
Redis
默认只允许本机访问,可是有时候我们也需要 Redis 被远程访问。
1 | 复制代码vi /etc/redis.conf |
找到 bind 那行配置,默认是: # bind 127.0.0.1
去掉#
注释并改为: bind 0.0.0.0
此设置会变成允许所有远程访问。如果想指定限制访问,可设置对应的IP。
3.3 配置Redis日志记录:
找到logfile
那行配置,默认是:logfile ""
,改为logfile /var/log/redis_6379.log
3.4 设置 Redis 请求密码:
1 | 复制代码vi /etc/redis.conf |
找到默认是被注释的这一行:# requirepass foobared
去掉注释,把 foobared
改为你想要设置的密码,比如我打算设置为:123456
,所以我改为:requirepass "123456"
修改之后重启下服务
有了密码之后,进入客户端,就得这样访问:redis-cli -h 127.0.0.1 -p 6379 -a 123456
4. Redis常用操作
4.1 启动
1 | 复制代码/usr/local/redis/bin/redis-server /etc/redis.conf |
4.2 关闭
1 | 复制代码/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown |
4.3 查看是否启动
1 | 复制代码ps -ef | grep redis |
4.4 进入客户端
1 | 复制代码redis-cli |
4.5 关闭客户端
1 | 复制代码redis-cli shutdown |
4.6 设置开机自动启动配置
1 | 复制代码echo "/usr/local/redis/bin/redis-server /etc/redis.conf" >> /etc/rc.local |
4.7 开放防火墙端口
1 | 复制代码添加规则:iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT |
5. 将Redis注册为系统服务
在/etc/init.d目录下添加Redis服务的启动,暂停和重启脚本:
1 | 复制代码vi /etc/init.d/redis |
脚本内容如下:
1 | 复制代码#!/bin/sh |
赋予脚本权限
1 | 复制代码chmod 755 /etc/init.d/redis |
启动、停止和重启:
1 | 复制代码service redis start |
至此,Redis
单机服务器已搭建完毕,下面我们看看主从架构如何搭建。
搭建Redis主从架构
1. redis-server说明
1 | 复制代码172.16.2.185:6379 主 |
2. Redis主从架构配置
- 编辑从机的
Redis
配置文件,找到 210 行(大概),默认这一行应该是注释的:# slaveof <masterip> <masterport>
- 我们需要去掉该注释,并且填写我们自己的主机的 IP 和 端口,比如:
slaveof 172.16.2.185 6379
,如果主机设置了密码,还需要找到masterauth <master-password>
这一行,去掉注释,改为masterauth 主机密码
。 - 配置完成后重启从机
Redis
服务 - 重启完之后,进入主机的
redis-cli
状态下redis-cli -h 127.0.0.1 -p 6379 -a 123456
,输入:INFO replication
可以查询到当前主机的Redis
处于什么角色,有哪些从机已经连上主机。
主机信息172.16.2.185
1 | 复制代码# Replication |
从机信息172.16.2.181
1 | 复制代码# Replication |
- 此时已经完成了主从配置,我们可以测试下:
我们进入主机的redis-cli
状态,然后set
某个值,比如:set myblog YouMeek.com
- 我们切换进入从机的
redis-cli
的状态下,获取刚刚设置的值看是否存在:get myblog
,此时,我们可以发现是可以获取到值的。
3. Redis主从架构总结
- 需要注意的是:从库不具备写入数据能力,不然会报错。 从库只有只读能力。
- 主从架构的优点:除了减少主库连接的压力,还有可以关掉主库的持久化功能,把持久化的功能交给从库进行处理。
- 第一个从库配置的信息是连上主库,后面的第二个从库配置的连接信息是连上第一个从库, 假如还有第三个从库的话,我们可以把第三个从库的配置信息连上第二个从库上,以此类推。
Redis Sentinel高可用架构搭建
1. 自动故障转移
- 虽然使用主从架构配置
Redis
做了备份,看上去很完美。但由于Redis
目前只支持主从复制备份(不支持主主复制),当主Redis
挂了,从Redis
只能提供读服务,无法提供写服务。所以,还得想办法,当主Redis
挂了,让从Redis
升级成为主Redis
。 - 这就需要自动故障转移,
Redis Sentinel
带有这个功能,当一个主Redis
不能提供服务时,Redis Sentinel
可以将一个从Redis
升级为主Redis
,并对其他从Redis
进行配置,让它们使用新的主Redis
进行复制备份。
注意:搭建Redis Sentinel
推荐至少3台服务器,但由于楼主偷懒,下面用例只用了2台服务器。
Redis Sentinel
的主要功能如下:
- 监控:哨兵不断的检查
master
和slave
是否正常的运行。 - 通知:当监控的某台
Redis
实例发生问题时,可以通过API
通知系统管理员和其他的应用程序。 - 自动故障转移:如果一个
master
不正常运行了,哨兵可以启动一个故障转移进程,将一个slave
升级成为master
,其他的slave
被重新配置使用新的master
,并且应用程序使用Redis
服务端通知的新地址。 - 配置提供者:哨兵作为
Redis
客户端发现的权威来源:客户端连接到哨兵请求当前可靠的master
的地址。如果发生故障,哨兵将报告新地址。
默认情况下,每个Sentinel
节点会以每秒一次的频率对Redis
节点和其它的Sentinel
节点发送PING
命令,并通过节点的回复来判断节点是否在线。
如果在down-after-millisecondes
毫秒内,没有收到有效的回复,则会判定该节点为主观下线。
如果该节点为master
,则该Sentinel
节点会通过sentinel is-master-down-by-addr
命令向其它sentinel
节点询问对该节点的判断,如果超过<quorum>
个数的节点判定master
不可达,则该sentinel
节点会将master
判断为客观下线。
这个时候,各个Sentinel
会进行协商,选举出一个领头Sentinel
,由该领头Sentinel
对master
节点进行故障转移操作。
故障转移包含如下三个操作:
- 在所有的
slave
服务器中,挑选出一个slave
,并将其转换为master
。 - 让其它
slave
服务器,改为复制新的master
。 - 将旧
master
设置为新master
的slave
,这样,当旧的master
重新上线时,它会成为新master
的slave
。
2. 搭建Redis Sentinel高可用架构
这里使用两台服务器,每台服务器上开启一个redis-server
和redis-sentinel
服务。
redis-server说明
1 | 复制代码172.16.2.185:6379 主 |
redis-sentinel说明
1 | 复制代码172.16.2.185:26379 |
2.1 建立Redis配置文件
如果要做自动故障转移,则建议所有的redis.conf
都设置masterauth
,因为自动故障只会重写主从关系,即slaveof
,不会自动写入masterauth
。如果Redis
原本没有设置密码,则可以忽略。
Redis
程序上面已经安装过了,我们只需增加redis-sentinel
的相关配置即可,将 redis-sentinel
的配置文件拷贝到系统配置目录/etc/
下,sentinel.conf
是 redis-sentinel
的配置文件,sentinel.conf
在 Redis
源码目录。
1 | 复制代码cp /usr/local/redis-4.0.2/sentinel.conf /etc/ |
修改sentinel.conf
配置文件内容如下:
1 | 复制代码vi /etc/sentinel.conf |
1 | 复制代码protected-mode no |
在配置最后加上
1 | 复制代码logfile /var/log/sentinel.log |
配置文件说明:
1.port :当前Sentinel服务运行的端口
2.dir : Sentinel服务运行时使用的临时文件夹
3.sentinel monitor master001 192.168.110.10163792:Sentinel去监视一个名为master001的主redis实例,这个主实例的IP地址为本机地址192.168.110.101,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
4.sentinel down-after-milliseconds master001 30000:指定了Sentinel认为Redis实例已经失效所需的毫秒数。当实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行
5.sentinel parallel-syncs master001 1:指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
6.sentinel failover-timeout master001 180000:如果在该时间(ms)内未能完成failover操作,则认为该failover失败
7.sentinel notification-script :指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,但是很常用
2.2 开放防火墙端口
1 | 复制代码添加规则:iptables -I INPUT -p tcp -m tcp --dport 26379 -j ACCEPT |
2.3 启动redis-sentinel
1 | 复制代码redis-sentinel /etc/sentinel.conf |
在任意一台机子均可查看到相关服务信息
1 | 复制代码redis-cli -h 127.0.0.1 -p 26379 |
1 | 复制代码# Sentinel |
3. 自动故障转移测试
3.1 停止主Redis
1 | 复制代码redis-cli -h 172.16.2.185 -p 6379 -a 123456 shutdown |
3.2 查看redis-sentinel的监控状态
1 | 复制代码# Sentinel |
发现从库提升为主库。
3.3 注意事项
- 如果停掉
master
后,Sentinel
显示足够数量的sdown
后,没有出现odown
或try-failover
,则检查密码等配置是否正确 - 如果停掉
master
后,试图切换的时候,发现日志出现failover-abort-not-elected
,则分2种情况分别解决:
- 如果
Redis
实例没有配置
1 | 复制代码protected-mode yes |
则在Sentinel
配置文件加上protected-mode no
即可
- 如果
Redis
实例有配置
1 | 复制代码protected-mode yes |
则在Sentinel
配置文件加上
1 | 复制代码protected-mode yes |
至此,redis的高可用方案已经搭建完成。
VIP对外提供虚拟IP实现高可用
1. 现有情况概述
客户端程序(如JAVA程序)连接Redis
时需要ip
和port
,但redis-server
进行故障转移时,主Redis
是变化的,所以ip
地址也是变化的。客户端程序如何感知当前主Redis
的ip
地址和端口呢?redis-sentinel
提供了接口,请求任何一个Sentinel
,发送SENTINEL get-master-addr-by-name <master name>
就能得到当前主Redis
的ip
和port
。
客户端每次连接Redis
前,先向sentinel
发送请求,获得主Redis
的ip
和port
,然后用返回的ip
和port
连接Redis
。
这种方法的缺点是显而易见的,每次操作Redis
至少需要发送两次连接请求,第一次请求Sentinel
,第二次请求Redis
。
更好的办法是使用VIP
,当然这对配置的环境有一定的要求,比如Redis
搭建在阿里云服务器上,可能不支持VIP
。
VIP
方案是,Redis
系统对外始终是同一ip地址,当Redis
进行故障转移时,需要做的是将VIP
从之前的Redis
服务器漂移到现在新的主Redis
服务器上。
比如:当前Redis
系统中主Redis
的ip
地址是172.16.2.185
,那么VIP(172.16.2.250)
指向172.16.2.185
,客户端程序用VIP(172.16.2.250)
地址连接Redis
,实际上连接的就是当前主Redis
,这样就避免了向Sentinel
发送请求。
当主Redis
宕机,进行故障转移时,172.16.2.181
这台服务器上的Redis
提升为主,这时VIP(172.16.2.250)
指向172.16.2.181
,这样客户端程序不需要修改任何代码,连接的是172.16.2.181
这台主Redis
。
2.漂移VIP实现Redis故障转移
那么现在的问题是,如何在进行Redis
故障转移时,将VIP
漂移到新的主Redis
服务器上。
这里可以使用Redis Sentinel
的一个参数client-reconfig-script
,这个参数配置执行脚本,Sentinel
在做failover
的时候会执行这个脚本,并且传递6个参数<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>
,其中<to-ip>
是新主Redis
的IP
地址,可以在这个脚本里做VIP
漂移操作。
1 | 复制代码sentinel client-reconfig-script mymaster /opt/notify_mymaster.sh |
修改两个服务器的redis-sentinel
配置文件/etc/sentinel.conf
,增加上面一行。然后在/opt/
目录下创建notify_mymaster.sh
脚本文件,这个脚本做VIP
漂移操作,内容如下:
1 | 复制代码vi /opt/notify_mymaster.sh |
1 | 复制代码#!/bin/bash |
赋予脚本权限
1 | 复制代码chmod 755 /opt/notify_mymaster.sh |
现在当前主Redis
是172.16.2.185
,需要手动绑定VIP
到该服务器上。
1 | 复制代码/sbin/ip addr add 172.16.2.250/24 dev eth1 |
由于VIP只能绑定只有一台机子,所以建议将改为bind 0.0.0.0
添加至redis.conf
中
1 | 复制代码vi /etc/redis.conf |
设置bind 0.0.0.0
由于VIP只能绑定只有一台机子,所以建议将改为bind 0.0.0.0
添加至sentinel.conf
中
1 | 复制代码vi /etc/sentinel.conf |
设置bind 0.0.0.0
重启Redis
1 | 复制代码service redis restart` |
重启Sentinel
1 | 复制代码redis-sentinel /etc/sentinel.conf |
随后我们在另一台机器172.16.2.181
上,通过VIP
访问主机
1 | 复制代码redis-cli -h 172.16.2.250 -p 6379 -a 123456 INFO replication |
可正常通讯,信息如下:
1 | 复制代码# Replication |
访问主机的Sentinel
1 | 复制代码redis-cli -h 172.16.2.250 -p 26379 INFO sentinel |
可正常通讯,信息如下:
1 | 复制代码# Sentinel |
下面关闭主机的Redis
服务,看看VIP是否漂移到另一台服务器上。
1 | 复制代码redis-cli -h 172.16.2.185 -p 6379 -a 123456 shutdown |
查看是否已进行切换
1 | 复制代码redis-cli -h 172.16.2.250 -p 26379 INFO sentinel |
1 | 复制代码# Sentinel |
通过查询Sentinel
发现从机172.16.2.181
提升为主。
通过访问VIP
的方式连接Redis
1 | 复制代码redis-cli -h 172.16.2.250 -p 6379 -a 123456 INFO replication |
1 | 复制代码# Replication |
从上面信息可知,VIP
已经飘移成功。可喜可贺,大吉大利,晚上吃鸡。
总结
至此,高可用Redis
缓存服务已搭建完毕,迟点会再出一篇文章教大家如何通过JAVA
连接Redis
进行相关操作。至于Redis Cluster
集群方案,等有空再搭建然后再和大家一同分享。
参考文章
redis sentinel 主从切换(failover)解决方案,详细配置
本文转载自: 掘金