关于哨兵模式的讲解,强烈推荐 [【深入学习redis(4):哨兵】](https://www.cnblogs.com/kismetv/p/9609938.html) # Linux哨兵模式 ## 安装Redis 1. [下载tar安装包](https://redis.io/download/) 2. 解压 ```shell tar -zxvf redis-7.0.4.tar.gz -C /usr/local/ #重命名 mv /usr/local/redis-7.0.4 /usr/local/redis ``` 3. 安装 ```shell #切换到解压目录 cd /usr/local/redis/ #编译 make #安装 make install PREFIX=/usr/local/redis ``` > make:根据makefile文件将源代码编译成可执行文件 > > make install:将可执行文件及其依赖库复制到安装目录 > > make install PREFIX=/usr/local/redis :这里多了一个关键字 PREFIX= 用于指定程序存放的路径,可执行文件默认存放在/usr/local/bin目录,库文件默认存放在/usr/local/lib目录,配置文件默认存放在/usr/local/etc目录,这里指定好目录也方便后续的卸载,后续直接rm -rf /usr/local/redis 即可删除redis。 4. 启动 ```shell /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf ``` 5. 登录客户端 ```shell /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 ``` ## redis实例 install_server.sh 可以执行一次或多次,一个物理机可以有多个redis实例,通过port区分,可执行程序就一份在目录,但是内存中多个实例要有多个配置文件 ```shell #执行redis自带的脚本安装实例 /usr/local/redis/utils/install_server.sh ``` 遇到第1个问题: ``` This systems seems to use systemd. Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry! ``` 解决:编辑脚本,注释掉部分代码 ```shell vim /usr/local/redis/utils/install_server.sh # 如下 #bail if this system is managed by systemd/usr/local/redis/utils/install_server.sh #_pid_1_exe="$(readlink -f /proc/1/exe)" #if [ "${_pid_1_exe##*/}" = systemd ] #then # echo "This systems seems to use systemd." # echo "Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!" # exit 1 #fi #unset _pid_1_exe ``` 执行步骤如下: ```shell [root@VM-24-15-centos redis]# /usr/local/redis/utils/install_server.sh Welcome to the redis service installer This script will help you easily set up a running redis server Please select the redis port for this instance: [6379] Selecting default: 6379 Please select the redis config file name [/etc/redis/6379.conf] /usr/local/redis/6379.conf Please select the redis log file name [/var/log/redis_6379.log] Selected default - /var/log/redis_6379.log Please select the data directory for this instance [/var/lib/redis/6379] /usr/local/redis/data/6379 Please select the redis executable path [] /usr/local/redis/bin/redis-server Selected config: Port : 6379 Config file : /usr/local/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /usr/local/redis/data/6379 Executable : /usr/local/redis/bin/redis-server Cli Executable : /usr/local/redis/bin/redis-cli Is this ok? Then press ENTER to go on or Ctrl-C to abort. Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service... Successfully added to chkconfig! Successfully added to runlevels 345! /var/run/redis_6379.pid exists, process is already running or crashed Installation successful! ``` 常用操作: > 此处的service name来自上面的 `Copied /tmp/6379.conf => /etc/init.d/redis_6379` ,末尾的 redis-6379 就是service name ```shell #启动 service redis_6379 start #关闭 service redis_6379 stop #重启 service redis_6379 restart #查看状态 service redis_6379 status ``` ## 配置文件redis.conf 配置文件 /usr/local/redis/redis.conf ,也可以通过 redis-cli 登录成功之后,执行 `config get * ` 查看配置项 这里列出了比较重要的配置 | 配置项名称 | 配置项值范围 | 说明 | | -------------- | ------------------------------- | ------------------------------------------------------------ | | daemonize | yes、no | yes表示启用守护进程,默认是no即不以守护进程方式运行。其中Windows系统下不支持启用守护进程方式运行 | | port | | 指定 Redis 监听端口,默认端口为 6379 | | bind | | 绑定的主机地址,如果需要设置远程访问则直接将这个属性注释掉或者改为bind * 即可,这个属性和下面的protected-mode控制了是否可以远程访问 | | protected-mode | yes 、no | 保护模式,该模式控制外部网是否可以连接redis服务,默认是yes,所以默认我们外网是无法访问的,如需外网连接rendis服务则需要将此属性改为no。 | | timeout | 300 | 当客户端闲置多长时间后关闭连接,如果指定为 0,表示关闭该功能 | | loglevel | debug、verbose、notice、warning | 日志级别,默认为 notice | | databases | 16 | 设置数据库的数量,默认的数据库是0。整个通过客户端工具可以看得到 | | rdbcompression | yes、no | 指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大。 | | dbfilename | dump.rdb | 指定本地数据库文件名,默认值为 dump.rdb | | dir | | 指定本地数据库存放目录 | | requirepass | | 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH \ 命令提供密码,默认关闭 | | maxclients | 0 | 设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息。 | | maxmemory | XXX \ | 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区。配置项值范围列里XXX为数值。 | **修改配置文件:** * 将daemonize改为yes,这样启动后redis就自动后台运行了 * 将bind 行注释掉,且将protected-mode设置为no,这样启动后就可以在外网访问了 * 设置 requirepass redis123,这样登录时就需要密码了 ```shell /usr/local/redis/bin/redis-cli -h ip -p 6379 -a redis123 ``` ## 查看redis运行状态 ```shell #查看redis进程 ps -ef | grep redis #根据端口查看 netstat -tunlp | grep 6379 #关闭redis #(注意,配置了 requirepass 时,使用 service redis_6379 stop 会无法关闭redis) #登录redis客户端后,执行 shutodwn /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 -a redis123 ``` ## 一主两从 1. 执行 `/usr/local/redis/utils/install_server.sh` 安装 6379、6380、6381 三个redis实例,配置如下 ``` Selected config: Port : 6379 Config file : /usr/local/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /usr/local/redis/data/6379 Executable : /usr/local/redis/bin/redis-server Cli Executable : /usr/local/redis/bin/redis-cli Selected config: Port : 6380 Config file : /usr/local/redis/6380.conf Log file : /var/log/redis_6380.log Data dir : /usr/local/redis/data/6380 Executable : /usr/local/redis/bin/redis-server Cli Executable : /usr/local/redis/bin/redis-cli Selected config: Port : 6381 Config file : /usr/local/redis/6381.conf Log file : /var/log/redis_6381.log Data dir : /usr/local/redis/data/6381 Executable : /usr/local/redis/bin/redis-server Cli Executable : /usr/local/redis/bin/redis-cli ``` 2. 分别修改配置 > * 此处省略 install_server.sh 安装redis实例时设定好了配置,比如 port、log file、data dir。 > * replicaof 是新版本的命令,旧版本是 slaveof 命令 **6379.conf** ```conf #允许后台运行 daemonize yes #注释掉bind #bind 127.0.0.1 -::1 #关闭保护模式,允许行外网连接 protected-mode no #访问密码 requirepass redis123 ``` **6380.conf** ```conf #允许后台运行 daemonize yes #注释掉bind #bind 127.0.0.1 -::1 #关闭保护模式,允许行外网连接 protected-mode no #访问密码 requirepass redis123 #主节点ip和端口 replicaof 81.70.105.158 6379 #连接主节点所使用的密码 masterauth "redis123" ``` **6381.conf** ```conf #允许后台运行 daemonize yes #注释掉bind #bind 127.0.0.1 -::1 #关闭保护模式,允许行外网连接 protected-mode no #访问密码 requirepass redis123 #主节点ip和端口 replicaof 81.70.105.158 6379 #连接主节点所使用的密码 masterauth "redis123" ``` 3. 启动 >注意,首次安装redis实例后,就自动运行了,改完配置文件后需重启。 ```shell service redis_6379 start service redis_6380 start service redis_6381 start ``` 4. 验证是否成功,看到从节点状态 online 说明主从环境搭建成功了 ```shell [root@VM-24-15-centos redis]# /usr/local/redis/bin/redis-cli -h 81.70.105.158 -p 6379 -a redis123 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=252,lag=0 slave1:ip=127.0.0.1,port=6380,state=online,offset=252,lag=0 master_failover_state:no-failover master_replid:be99f9284866de72ad2c7e4c70c4d44cdffad263 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:252 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:252 ``` ## 三个哨兵 1. 配置三个sentinel.conf **sentinel-26379.conf** ```conf port 26379 daemonize yes logfile "/var/log/redis-sentinel-26379.log" sentinel monitor mymaster 81.70.105.158 6379 2 sentinel auth-pass mymaster redis123 ``` **sentinel-26380.conf** ```conf port 26380 daemonize yes logfile "/var/log/redis-sentinel-26380.log" sentinel monitor mymaster 81.70.105.158 6379 2 sentinel auth-pass mymaster redis123 ``` **sentinel-26381.conf** ```conf port 26381 daemonize yes logfile "/var/log/redis-sentinel-26381.log" sentinel monitor mymaster 81.70.105.158 6379 2 sentinel auth-pass mymaster redis123 ``` 2. 启动 哨兵节点的启动有两种方式,二者作用是完全相同的: ```shell #第一种启动方式 /usr/local/redis/bin/redis-sentinel sentinel-26379.conf #第二种启动方式 /usr/local/redis/bin/redis-server sentinel-26379.conf --sentinel /usr/local/redis/bin/redis-sentinel sentinel-26379.conf /usr/local/redis/bin/redis-sentinel sentinel-26380.conf /usr/local/redis/bin/redis-sentinel sentinel-26381.conf ``` 3. 验证是否成功,看到最后 status=ok 说明成功了 ``` [root@centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 26379 127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_tilt_since_seconds:-1 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=81.70.105.158:6379,slaves=2,sentinels=3 ``` 4. 故障转移 关闭redis-6379节点,然后观察哨兵选出来的新master节点 ```shell [root@centos ~]# /usr/local/redis/bin/redis-cli -h 81.70.105.158 -p 6379 -a redis123 81.70.105.158:6379>shutdown [root@centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 26379 127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_tilt_since_seconds:-1 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=81.70.105.158:6380,slaves=2,sentinels=3 ``` ![image-20220906180431684](imgs/image-20220906180431684.png) # Windows哨兵模式 从 [https://github.com/tporadowski/redis/releases](https://github.com/tporadowski/redis/releases) 下载windows版的redis,自行下载解压。 ## 一主两从 1. 复制三份 redis.windows.conf,分别如下配置 **redis-6379.windows.conf** ```conf bind 127.0.0.1 port 6379 ``` **redis-6380.windows.conf** ```conf bind 127.0.1 port 6380 slaveof 127.0.0.1 6379 ``` **redis-6381.windows.conf** ```conf bind 127.0.1 port 6381 slaveof 127.0.0.1 6379 ``` 2. 启动 ```shell redis-server.exe redis-6379.windows.conf redis-server.exe redis-6380.windows.conf redis-server.exe redis-6381.windows.conf ``` 3. 验证是否成功,看到从节点状态 online 说明主从环境搭建成功了 ```shell redis-cli.exe -h 127.0.0.1 -p 6379 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=98,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=98,lag=0 master_replid:677245c1292f2244597f22a12c85730f236fa707 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:98 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:98 ``` ## 三个哨兵 1. 创建三个配置文件 sentinel-26379.windows.conf ```shell bind 127.0.0.1 port 26379 sentinel monitor mymaster 127.0.0.1 6379 2 ``` sentinel-26380.windows.conf ```shell bind 127.0.0.1 port 26380 sentinel monitor mymaster 127.0.0.1 6379 2 ``` sentinel-26381.windows.conf ```shell bind 127.0.0.1 port 26381 sentinel monitor mymaster 127.0.0.1 6379 2 ``` 2. 启动哨兵 ```shell redis-server.exe sentinel-26379.windows.conf --sentinel redis-server sentinel-26380.windows.conf --sentinel redis-server sentinel-26381.windows.conf --sentinel ``` 3. 验证是否成功,看到最后 status=ok 说明成功了 ```shell 127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3 ``` 4. 演示故障自动切换 关掉主节点 6379,等一会,就会发现哨兵切换了主节点,重新启动 6379 节点,它就变成了从节点了 ```shell redis-cli.exe -h 127.0.0.1 -p 6379 127.0.0.1:6379> info replication # Replication role:slave master_host:127.0.0.1 master_port:6380 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:56440 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:8f282577c2e4ddeb9794f88757e5dad7870e5e6d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:56440 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:55487 repl_backlog_histlen:954 ``` ## 遇到的问题 代码客户端连接redis,报错 All sentinels down, cannot determine where is mymaster master is running... 或者 Could not get a resource from the pool 参考这篇博客:https://www.jianshu.com/p/098494958892 好了,认真读过 [【深入学习redis(4):哨兵】](https://www.cnblogs.com/kismetv/p/9609938.html) ,所以这个问题已经不再是问题了 > 通过客户端原理的介绍,可以加深对哨兵功能的理解: > > (1)配置提供者:客户端可以通过哨兵节点+masterName获取主节点信息,在这里哨兵起到的作用就是配置提供者。 > > **需要注意的是,哨兵只是配置提供者,而不是代理**。二者的区别在于:如果是配置提供者,客户端在通过哨兵获得主节点信息后,会直接建立到主节点的连接,后续的请求(如set/get)会直接发向主节点;如果是代理,客户端的每一次请求都会发向哨兵,哨兵再通过主节点处理请求。 > > 举一个例子可以很好的理解哨兵的作用是配置提供者,而不是代理。在前面部署的哨兵系统中,将哨兵节点的配置文件进行如下修改: > > ``` > sentinel monitor mymaster 192.168.92.128 6379 2 > 改为 > sentinel monitor mymaster 127.0.0.1 6379 2 > ``` > > 然后,将前述客户端代码在局域网的另外一台机器上运行,会发现客户端无法连接主节点;这是因为哨兵作为配置提供者,客户端通过它查询到主节点的地址为127.0.0.1:6379,客户端会向127.0.0.1:6379建立redis连接,自然无法连接。如果哨兵是代理,这个问题就不会出现了。 注意一点:哨兵程序监控端口和 redis 服务端口都要开放给客户端,否则就访问不通。 我本地开发环境就是这种情况,可以访问通监控端口,但是无法访问redis服务端口。这也再次说明了哨兵只是配置提供者,而不是代理。 # 不停机修改密码 昨天网络安全部反馈redis服务器有弱口令漏洞隐患,要求三个工作日修复 哨兵模式 ```shell config set masterauth 新密码 config set requirepass 新密码 auth 新密码 config rewrite # 主从节点依次执行上面的修改,修改之后redis和sentinel配置文件会自动更新为该密码。 ```