4.1 Centos7 安装redis6.X

学习目标

  • 在Centos中安装redis
  • 配置Redis主从
  • 配置Redis哨兵集群
  • 使用RedisTemplate连接Redis哨兵集群

1. 安装redis依赖

安装redis之前,先安装redis依赖
yum -y install gcc gcc-c++ make tcl
![image.png](https://img-blog.csdnimg.cn/img_convert/0bfe4c679725aa93650a45d9c3c37a8d.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=86&id=u360ab260&margin=[object Object]&name=image.png&originHeight=107&originWidth=594&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6166&status=done&style=none&taskId=u591f5898-f469-4805-b06d-703f88003e6&title=&width=475.2)
结果:
![image.png](https://img-blog.csdnimg.cn/img_convert/5318f750233d2057e142ac2c7c6aaf71.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=214&id=uf51e76af&margin=[object Object]&name=image.png&originHeight=268&originWidth=882&originalType=binary&ratio=1&rotation=0&showTitle=false&size=16622&status=done&style=none&taskId=ue099065d-518e-40b4-b692-a5963ff602a&title=&width=705.6)

编译安装需要gcc5.3以上,可以用gcc -v 命令查看当前版本号
![image.png](https://img-blog.csdnimg.cn/img_convert/ce91b5ac3495ae6030887542a771301d.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=321&id=u791f439a&margin=[object Object]&name=image.png&originHeight=401&originWidth=1131&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42073&status=done&style=none&taskId=u4bba6629-6f8b-43a2-8d6d-e0a314e1fe3&title=&width=904.8)
使用下面的命令升级到gcc9.1
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

scl enable devtoolset-9 bash
#scl命令启用只是临时的,新开的会话默认还是原gcc版本。
#如果要长期使用gcc 9.1的话执行下面的命令即可:
echo -e “\nsource /opt/rh/devtoolset-9/enable” >>/etc/profile

2. 安装Redis

下载安装包 redis-6.2.6.tar.gz
官网地址:http://redis.io/download
所有版本:https://download.redis.io/releases/
下载地址:https://download.redis.io/releases/redis-6.2.6.tar.gz
![image.png](https://img-blog.csdnimg.cn/img_convert/3a746dbe1d63e4abffa79e01f5fbc301.png#clientId=u7badd0a4-d061-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=643&id=ua431651a&margin=[object Object]&name=image.png&originHeight=1286&originWidth=2560&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1088301&status=done&style=none&taskId=u858e605e-8531-4d64-bf0b-84a23b1689c&title=&width=1280)

创建文件夹
![image.png](https://img-blog.csdnimg.cn/img_convert/2fd06e873d32abd18597fb738adeeb07.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=134&id=u54c2c4d0&margin=[object Object]&name=image.png&originHeight=167&originWidth=538&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11658&status=done&style=none&taskId=ua95eae04-d088-453d-bf7d-9cfcc3df8f1&title=&width=430.4)
上传redsi的压缩文件到 /root/soft/redis,并解压:**tar -zvxf redis-6.2.6.tar.gz **
![image.png](https://img-blog.csdnimg.cn/img_convert/dc27e897ae67374a76f648b2ce4313cf.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=103&id=u821934ba&margin=[object Object]&name=image.png&originHeight=129&originWidth=636&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10827&status=done&style=none&taskId=u1806cdc0-8d7b-4ada-a100-de327c7a89c&title=&width=508.8)
为了方便重新命名一下:mv redis-6.2.6 redis
![image.png](https://img-blog.csdnimg.cn/img_convert/4c07e437d99588ce37d341ca39186125.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=135&id=uf3727ccb&margin=[object Object]&name=image.png&originHeight=169&originWidth=651&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12989&status=done&style=none&taskId=u685e9ce2-a248-49cb-9d53-b5b15872731&title=&width=520.8)
切换到 redis 文件夹,执行:make
![image.png](https://img-blog.csdnimg.cn/img_convert/d00809624539dc8b489f0f41de129d6b.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=100&id=udc724ebf&margin=[object Object]&name=image.png&originHeight=125&originWidth=384&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7117&status=done&style=none&taskId=ud9ddd1bc-ad18-4cb9-8c99-a291cccb8ff&title=&width=307.2)
结果
![image.png](https://img-blog.csdnimg.cn/img_convert/375fb1b37c50f95e9eb377c886a2272f.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=150&id=u372151c5&margin=[object Object]&name=image.png&originHeight=188&originWidth=485&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10808&status=done&style=none&taskId=ub3debd21-b7e9-4d89-9a5d-7567531c3da&title=&width=388)
然后执行:make test,这个时间比较长
![image.png](https://img-blog.csdnimg.cn/img_convert/b93c4b5e169428b6584a1cc3052ad00e.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=144&id=u04c09e35&margin=[object Object]&name=image.png&originHeight=180&originWidth=452&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9400&status=done&style=none&taskId=u2fe01758-3778-4fac-8781-ca32d1bd214&title=&width=361.6)
执行安装命令:make install
![image.png](https://img-blog.csdnimg.cn/img_convert/aeeb06ea681bb46c666dd4d058158f8e.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=248&id=u628570c7&margin=[object Object]&name=image.png&originHeight=310&originWidth=559&originalType=binary&ratio=1&rotation=0&showTitle=false&size=19909&status=done&style=none&taskId=u5a157b98-6255-4481-93ff-bc337ee6e99&title=&width=447.2)
执行:redis-server,启动redis
![image.png](https://img-blog.csdnimg.cn/img_convert/442301c48004fa120f9120a22c580271.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=422&id=ua79a43bf&margin=[object Object]&name=image.png&originHeight=527&originWidth=1136&originalType=binary&ratio=1&rotation=0&showTitle=false&size=29621&status=done&style=none&taskId=ub9bbfc33-3478-4894-b90d-cae8b544ddc&title=&width=908.8)
但是这样子发现redis并不是后台运行,如果要后台运行还要进行一些配置
这时候终止redis:ctrl + c

3. 简单配置

切换到 /root/soft/redis 目录,创建 db/6379 目录(存放redis持久化文件)
![image.png](https://img-blog.csdnimg.cn/img_convert/76519dd5cce0cb4b1250504411608772.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=113&id=u21848f80&margin=[object Object]&name=image.png&originHeight=141&originWidth=494&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9911&status=done&style=none&taskId=u0cf9f1a2-af35-4cb9-9101-f26dadfd055&title=&width=395.2)
进入 src 文件夹,复制redis-server、redis-cli文件到 /root/soft/redis 目录(方便以后操作)
![image.png](https://img-blog.csdnimg.cn/img_convert/a020dd68b1f576ed38d346a50876c461.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=161&id=u51080027&margin=[object Object]&name=image.png&originHeight=201&originWidth=696&originalType=binary&ratio=1&rotation=0&showTitle=false&size=16675&status=done&style=none&taskId=uf7a84e74-63bf-4506-bdf7-4cb564223e4&title=&width=556.8)
进入 /root/soft/redis/redis 文件夹,复制 redis.conf 文件到 /root/soft/redis 目录
![image.png](https://img-blog.csdnimg.cn/img_convert/312376663790db30764deab8d9c2167b.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=190&id=u6ce2a3cf&margin=[object Object]&name=image.png&originHeight=238&originWidth=608&originalType=binary&ratio=1&rotation=0&showTitle=false&size=20413&status=done&style=none&taskId=uf4c2ff5f-ab25-4ecd-a8f6-a1fe4eb6df4&title=&width=486.4)
最终结果:
![image.png](https://img-blog.csdnimg.cn/img_convert/4385636bf9003b0653f9bf783b91466e.png#clientId=ue7011314-3c05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=166&id=ub488e9a2&margin=[object Object]&name=image.png&originHeight=207&originWidth=599&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17329&status=done&style=none&taskId=ue95c24a8-5f3a-4e64-b281-d160561a8cb&title=&width=479.2)
编辑redis.conf文件

  • daemonize yes (让redis后台运行)
  • dir /root/soft/redis/db/6379 (存放redis的持久化文件)

切换到 /root/soft/redis 目录,执行:redis-server redis.conf
![image.png](https://img-blog.csdnimg.cn/img_convert/62f5d6a2534740172698a427806cc890.png#clientId=u64143ac5-1bcd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=118&id=uf89eba67&margin=[object Object]&name=image.png&originHeight=147&originWidth=734&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12277&status=done&style=none&taskId=ua077cca7-eac4-4946-9968-066ce41bf11&title=&width=587.2)
尝试用 redis-cli 连接
![image.png](https://img-blog.csdnimg.cn/img_convert/07c3b7bad678660c5a4a965065eb35a4.png#clientId=u5cb5a5e3-e3f8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=146&id=mD8Pr&margin=[object Object]&name=image.png&originHeight=292&originWidth=1370&originalType=binary&ratio=1&rotation=0&showTitle=false&size=100631&status=done&style=none&taskId=uab0a79ba-026b-4ae5-a280-5ff22e384e9&title=&width=685)
退出 redis-cli,使用 exit 命令

但这时候关闭redis,就只能:kill -9 进程号

4. Redis 主从

单节点的redis,并发能力是有上限的,要进一步提高,就需要搭建集群,读写分离
![image.png](https://img-blog.csdnimg.cn/img_convert/68fbeb83536c3dffb15ba35dc5b0a5db.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=413&id=u0bf18815&margin=[object Object]&name=image.png&originHeight=826&originWidth=832&originalType=binary&ratio=1&rotation=0&showTitle=false&size=132260&status=done&style=none&taskId=ue2457500-50c6-4da0-9380-8e6a4e9568f&title=&width=416)

1. 准备

创建3个文件夹:7001、7002、7003
![image.png](https://img-blog.csdnimg.cn/img_convert/1c5de01bd99271dec623b7357a8b75a4.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=151&id=Ey22S&margin=[object Object]&name=image.png&originHeight=302&originWidth=1052&originalType=binary&ratio=1&rotation=0&showTitle=false&size=218404&status=done&style=none&taskId=uba0ab248-2009-4c7e-a88c-742db4a9b06&title=&width=526)
复制 redis.conf 文件到 7001、7002、7003 文件夹,执行下面的命令

 echo 7001 7002 7003 | xargs -t -n 1 cp redis.conf

![image.png](https://img-blog.csdnimg.cn/img_convert/62edf51ce893433926784ec8963c1d8c.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=84&id=ufca18f8e&margin=[object Object]&name=image.png&originHeight=168&originWidth=1048&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103600&status=done&style=none&taskId=u7bd47f32-7d10-4fd6-afa5-fd972d32ea8&title=&width=524)
在 7001、7002、7003 下,分别建立 db 和 logs 目录

修改配置文件,以 7001 为示例(注意:并不是用下面的配置去整个替换redis.conf中的内容

# 把192.168.56.103暴露出去,这样就可以通过这个ip连接redis
bind 192.168.56.103 127.0.0.1 -::1
# 端口
port 7001
# 进程文件
pidfile /var/run/redis_7001.pid
# 日志文件,需要提前建好logs文件夹
logfile /root/soft/redis/7001/logs/redis.log
# 持久化文件目录,需要提前建好db文件夹
dir /root/soft/redis/7001/db

# aof暂时关掉
appendonly no
# rdb也暂时恢复到默认配置

# 虚拟机有多个ip,为了避免混乱,方便主从通信,绑定一个ip
replica-announce-ip 192.168.56.103

7002 、7003 类似

2. 主从

让 7002、7003 作为 7001 的从节点
修改 7002 、7003 的配置文件

replicaof 192.168.56.103 7001
# 注意,redis 5.0之前的版本叫 slaveof

(注意:下面截图不用在意ip地址)
![image.png](https://img-blog.csdnimg.cn/img_convert/df3abb1ead486a2a8d5fa63d5aaf3e52.png#clientId=u3df18b83-6ade-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=110&id=PtsxN&margin=[object Object]&name=image.png&originHeight=137&originWidth=435&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12522&status=done&style=none&taskId=u12166e09-daa5-41bc-b705-0ffed2e4c73&title=&width=348)

切换到 /root/soft/redis 目录,分别启动
![image.png](https://img-blog.csdnimg.cn/img_convert/30195bad922bd36c2e0a2d9ce752cf2e.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=184&id=u184487b1&margin=[object Object]&name=image.png&originHeight=368&originWidth=1172&originalType=binary&ratio=1&rotation=0&showTitle=false&size=386957&status=done&style=none&taskId=u70f62482-7743-4a06-8f7e-c7443ecd5fa&title=&width=586)
可以看到启动成功3个 redis 实例

查看集群状态
![image.png](https://img-blog.csdnimg.cn/img_convert/f47bb97cb15f10fd39a38a71b8db73fc.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=226&id=u15a3c709&margin=[object Object]&name=image.png&originHeight=452&originWidth=1212&originalType=binary&ratio=1&rotation=0&showTitle=false&size=330217&status=done&style=none&taskId=u9bd60ca3-4d80-4359-8146-2e534b529fe&title=&width=606)

测试数据同步
在 7001 实例 设置一个key
![image.png](https://img-blog.csdnimg.cn/img_convert/f1f546b8652b4676a362a61a625762ff.png#clientId=u32b1df4c-d07f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=110&id=ud536523e&margin=[object Object]&name=image.png&originHeight=137&originWidth=462&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8925&status=done&style=none&taskId=u298cdb8c-9834-452f-9e73-8aa56b383ec&title=&width=369.6)
在 7002 实例可以获取到这个key
![image.png](https://img-blog.csdnimg.cn/img_convert/3f5683c3f96385cb1e6fbd03dc4836fe.png#clientId=u5643f7a2-d097-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=131&id=u87bf22f3&margin=[object Object]&name=image.png&originHeight=262&originWidth=804&originalType=binary&ratio=1&rotation=0&showTitle=false&size=127385&status=done&style=none&taskId=u26a7736d-1adf-4a8e-9289-91b6a49c084&title=&width=402)
而且,默认情况下,从节点不能写
![image.png](https://img-blog.csdnimg.cn/img_convert/84ff8e78d262c88a1ec77c58e60e004a.png#clientId=u1d2b6791-928a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=93&id=ubbc1d3d5&margin=[object Object]&name=image.png&originHeight=186&originWidth=1076&originalType=binary&ratio=1&rotation=0&showTitle=false&size=94002&status=done&style=none&taskId=u88448f32-f8bb-4ccc-8238-bf741751c93&title=&width=538)
对应的 配置
![image.png](https://img-blog.csdnimg.cn/img_convert/08d68c3b3f3950ab0b4cbb5d9ac8a3e9.png#clientId=u1d2b6791-928a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=162&id=u0cc05cd5&margin=[object Object]&name=image.png&originHeight=324&originWidth=1094&originalType=binary&ratio=1&rotation=0&showTitle=false&size=392047&status=done&style=none&taskId=u9c9e935b-fb80-4a2e-b5a0-030fb1dced2&title=&width=547)

3. 数据同步机制

1. 第一次同步,全量同步

在 /root/soft/redis 目录下,创建 7004,内容同7002、7003
启动 7001后,启动7004
![image.png](https://img-blog.csdnimg.cn/img_convert/2c35ead5fe985ffd62fb107c06f48a17.png#clientId=u32b1df4c-d07f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=93&id=ue4437b76&margin=[object Object]&name=image.png&originHeight=116&originWidth=594&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7489&status=done&style=none&taskId=u977fee6a-e5da-48c0-a054-23c05622a16&title=&width=475.2)
查看 7001 日志

15726:M 16 Jun 2022 23:58:54.577 * Ready to accept connections
                                  # 下面是启动7004后,7001的日志
                                  # 7004请求数据同步
15726:M 16 Jun 2022 23:59:25.227 * Replica 192.168.56.105:7004 asks for synchronization
                                  # 7004是第一次连接,所以请求全量同步
15726:M 16 Jun 2022 23:59:25.228 * Full resync requested by replica 192.168.56.105:7004
                                  # 创建:复制积压缓冲区,Mater只要有slave就会创建这个
15726:M 16 Jun 2022 23:59:25.228 * Replication backlog created, my new replication IDs are '70fd50d3011b7796ca452cac022f20d406e1e8a0' and '0000000000000000000000000000000000000000'
                                  # 执行 bgsave 生成 rdb 
15726:M 16 Jun 2022 23:59:25.228 * Starting BGSAVE for SYNC with target: disk
                                  # 启动一个后台线程生成rdb
15726:M 16 Jun 2022 23:59:25.229 * Background saving started by pid 16207
16207:C 16 Jun 2022 23:59:25.242 * DB saved on disk
16207:C 16 Jun 2022 23:59:25.243 * RDB: 4 MB of memory used by copy-on-write
15726:M 16 Jun 2022 23:59:25.315 * Background saving terminated with success
15726:M 16 Jun 2022 23:59:25.315 * Synchronization with replica 192.168.56.105:7004 succeeded

查看 7004 日志

16202:S 16 Jun 2022 23:59:25.226 * Ready to accept connections
                                  # 连接主节点
16202:S 16 Jun 2022 23:59:25.227 * Connecting to MASTER 192.168.56.105:7001
                                  # 开始数据同步
16202:S 16 Jun 2022 23:59:25.227 * MASTER <-> REPLICA sync started
16202:S 16 Jun 2022 23:59:25.227 * Non blocking connect for SYNC fired the event.
                                  # Mater已回复连接信息,可以进行数据同步
16202:S 16 Jun 2022 23:59:25.227 * Master replied to PING, replication can continue...
                                  # 不能进行增量同步
16202:S 16 Jun 2022 23:59:25.227 * Partial resynchronization not possible (no cached master)
                                  # 全量同步
16202:S 16 Jun 2022 23:59:25.229 * Full resync from master: 70fd50d3011b7796ca452cac022f20d406e1e8a0:0
16202:S 16 Jun 2022 23:59:25.316 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk
16202:S 16 Jun 2022 23:59:25.316 * MASTER <-> REPLICA sync: Flushing old data
16202:S 16 Jun 2022 23:59:25.316 * MASTER <-> REPLICA sync: Loading DB in memory
16202:S 16 Jun 2022 23:59:25.321 * Loading RDB produced by version 6.2.6
16202:S 16 Jun 2022 23:59:25.321 * RDB age 0 seconds
16202:S 16 Jun 2022 23:59:25.321 * RDB memory usage when created 1.83 Mb
16202:S 16 Jun 2022 23:59:25.321 # Done loading RDB, keys loaded: 0, keys expired: 0.
16202:S 16 Jun 2022 23:59:25.322 * MASTER <-> REPLICA sync: Finished with success

流程:
![image.png](https://img-blog.csdnimg.cn/img_convert/89851c8ea7a5f4dc387abe4b291c1d3f.png#clientId=u91a0b7ab-8a51-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=427&id=ued70dbea&margin=[object Object]&name=image.png&originHeight=854&originWidth=1490&originalType=binary&ratio=1&rotation=0&showTitle=false&size=482539&status=done&style=none&taskId=u4d2dc496-2aed-49ae-9a98-f8460acb327&title=&width=745)
第一阶段

  • slave 启动时,与 master 建立连接,并请求数据同步
    • slav建立连接时候会发送 runId 和 offset
      • offset:数据偏移量,第一次连接是-1,表示全量同步
      • runId :master的唯一标示,redis 在启动的时候,都会为自己生成一个ID,第一次salve传“?”
  • master 会判断这个 slave 是不是第一次连接
    • 是:会把offset 和 runId 发给 slave ,slave会保存这个信息

第二阶段

  • 然后 master 生成一个rdb,发送给 slave,slave拿到后清空本地数据,加载rdb文件
  • master 生成rdb的时候,正常接收客户端请求,会把命令记录到 replication_buffer 中(也叫复制缓冲区

第三阶段

  • master 发送 replication_buffer 中的命令 , slave接到后执行,全量同步完毕

2. 增量同步

一般情况下,当 slave 故障,重启后,会做增量同步
关闭 7004
![image.png](https://img-blog.csdnimg.cn/img_convert/235dfd3b09b9b841b29821eea028d678.png#clientId=u32b1df4c-d07f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=116&id=u35f52dec&margin=[object Object]&name=image.png&originHeight=145&originWidth=723&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13554&status=done&style=none&taskId=ucd657626-8719-4c76-b818-957c21f7e3b&title=&width=578.4)
使用 redis-cli 连接 7001,设置几个key
![image.png](https://img-blog.csdnimg.cn/img_convert/9c5fe362cb0a369d3d68b8a8c06919cd.png#clientId=u32b1df4c-d07f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=159&id=ud82f18ca&margin=[object Object]&name=image.png&originHeight=199&originWidth=506&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10468&status=done&style=none&taskId=ua552083a-299f-4b34-bee1-dc45fb235eb&title=&width=404.8)
再次启动 7004 ,然后查看日志
7001

                                 # 关闭7004时,有这句输出 
15726:M 17 Jun 2022 01:10:45.448 # Connection with replica 192.168.56.105:7004 lost.
                                 # 执行set命令时,生成了rdb文件
15726:M 17 Jun 2022 01:13:07.166 * 1 changes in 3600 seconds. Saving...
15726:M 17 Jun 2022 01:13:07.168 * Background saving started by pid 18474
18474:C 17 Jun 2022 01:13:07.272 * DB saved on disk
18474:C 17 Jun 2022 01:13:07.274 * RDB: 6 MB of memory used by copy-on-write
15726:M 17 Jun 2022 01:13:07.371 * Background saving terminated with success
                                 # 7004 请求数据同步
15726:M 17 Jun 2022 01:18:27.830 * Replica 192.168.56.105:7004 asks for synchronization
                                 # 接受同步请求,发送数据   
15726:M 17 Jun 2022 01:18:27.830 * Partial resynchronization request from 192.168.56.105:7004 accepted. Sending 5950 bytes of backlog starting from offset 1.

7004

23322:S 17 Jun 2022 01:18:27.830 * Ready to accept connections
23322:S 17 Jun 2022 01:18:27.830 * Connecting to MASTER 192.168.56.105:7001
23322:S 17 Jun 2022 01:18:27.830 * MASTER <-> REPLICA sync started
23322:S 17 Jun 2022 01:18:27.830 * Non blocking connect for SYNC fired the event.
23322:S 17 Jun 2022 01:18:27.830 * Master replied to PING, replication can continue...
                                 # 请求增量同步
23322:S 17 Jun 2022 01:18:27.830 * Trying a partial resynchronization (request 70fd50d3011b7796ca452cac022f20d406e1e8a0:1).
23322:S 17 Jun 2022 01:18:27.830 * Successful partial resynchronization with master.
23322:S 17 Jun 2022 01:18:27.830 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.

![image.png](https://img-blog.csdnimg.cn/img_convert/7f21896e93f5f92b4d4ebc8c83401426.png#clientId=u39074a5f-c998-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=372&id=rex4x&margin=[object Object]&name=image.png&originHeight=744&originWidth=1812&originalType=binary&ratio=1&rotation=0&showTitle=false&size=344973&status=done&style=none&taskId=u0cd0c963-2947-4471-a971-7e3880969ea&title=&width=906)
主从正常同步的时候,master会把命令写到 replication_buffer(复制缓冲区) 中,
同时也会写在 replication_backlog_buffer 中(也叫:复制积压缓冲区,默认1M大小

当 slave 断开,又重新连接的时候,master 会根据 offset ,从 repl_backlog 中获取增量数据给 slave
但是repl_backlog的大小有上限,写满后,新来的数据会覆盖最早的数据,如果 slave 断开时间太久,导致一部分数据还没有同步就被覆盖了,就只能最全量同步

5. Redis 哨兵

当主从集群下Master当宕机,Redis 的哨兵机制(Sentinel)会从Slave节点中选举一个新的Master
主要功能如下
(1)集群监控,负责监控redis master和slave是否正常工作
(2)故障转移,如果master node挂掉了,自动故障转移,从Slave节点中选举一个新的Master
(3)消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
如果故障转移发生了,通知client客户端新的master地址
![image.png](https://img-blog.csdnimg.cn/img_convert/3984e0582ee0abc46b0e6cb2da2bcc0a.png#clientId=uad24a40e-1501-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=473&id=u8feb1535&margin=[object Object]&name=image.png&originHeight=946&originWidth=1218&originalType=binary&ratio=1&rotation=0&showTitle=false&size=571565&status=done&style=none&taskId=u2c2d9ffc-fa35-4666-8314-2c23a71c944&title=&width=609)
总结:Redis哨兵用来监控主从集群,当Master宕机时,从Slave中选举新的Master

1. 集群监控

哨兵是基于心跳机制监控集群状态,每秒向集群中的实例发送ping命令

  • 如果某个哨兵节点发现某实例没在规定时间(down-after-milliseconds 配置)响应,
    则该实例:主观宕机(sdown)
  • 如果指定数量(quorum)的哨兵都认为这个实例宕机,则该实例:客观宕机(odown),quorum最好超过一半数量

![image.png](https://img-blog.csdnimg.cn/img_convert/94c895cc18ab4243d73937a9753f1220.png#clientId=uad24a40e-1501-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=376&id=u4b374718&margin=[object Object]&name=image.png&originHeight=752&originWidth=1174&originalType=binary&ratio=1&rotation=0&showTitle=false&size=519436&status=done&style=none&taskId=uac40356c-d83a-407d-ac32-dad33c33cef&title=&width=587)
上图中,一同有3个哨兵,其中2个都认为master宕机了,且quorum=2,那么这个master就是客观宕机,需要进行故障转移

2. 故障转移

一旦认为Master客观宕机,哨兵会在slave中选出一个最为新的Master,选举算法

  • 判断跟Master断开连接的时长,超过了down-after-milliseconds的10倍,排除这个slave
  • 判断salve的优先级replica-priority属性(老版本是slave-priority)越低,优先级就越高
  • 如果replica-priority相同,那么看replication offset,offset越大,优先级就越高
    • offset越大:数据越完整
  • 如果上面两个条件都相同,那么选择一个 run id 比较小的
    • runid是启动redis时生成的,通过 info server 命令可以查看runid
    • ![image.png](https://img-blog.csdnimg.cn/img_convert/227b40f9a1f465bcbfc7a15bb2df5e15.png#clientId=u6b0fb370-ee5b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=49&id=u366a516c&margin=[object Object]&name=image.png&originHeight=61&originWidth=394&originalType=binary&ratio=1&rotation=0&showTitle=false&size=4132&status=done&style=none&taskId=u4baf770e-44b4-44c8-9d69-c33bfd55764&title=&width=315.2)
    • ![image.png](https://img-blog.csdnimg.cn/img_convert/494b3768c6ad218e1f9f810a0c4767b2.png#clientId=u6b0fb370-ee5b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=81&id=u706df411&margin=[object Object]&name=image.png&originHeight=101&originWidth=452&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6276&status=done&style=none&taskId=uae7178c3-f293-48cd-926f-9650e64145f&title=&width=361.6)

一旦确定Master节点后,会选择一个哨兵节点,进行故障转移

  • 给备选的slave发送 **slave no none **命令,让该节点成为Master
  • 给其他slave节点发送 REPLICAOF(老版本是:slaveof) 命令,让这些slave成为新Master的从节点
  • 给故障的节点标记为slave,当节点恢复后,会自动成为从节点

![image.png](https://img-blog.csdnimg.cn/img_convert/61d570552661da8a1cfb44c1b4037212.png#clientId=uad24a40e-1501-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=433&id=u8a81746f&margin=[object Object]&name=image.png&originHeight=866&originWidth=1168&originalType=binary&ratio=1&rotation=0&showTitle=false&size=437216&status=done&style=none&taskId=ue40c4eba-3bee-42d9-b26a-398003221fe&title=&width=584)

3. 搭建哨兵集群

1. 配置

在 /root/soft/redis 目录下创建 3 个 文件夹
![image.png](https://img-blog.csdnimg.cn/img_convert/3b18ead42fb758867a0582d58dd19d4c.png#clientId=uad24a40e-1501-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=134&id=u5860dbbc&margin=[object Object]&name=image.png&originHeight=268&originWidth=976&originalType=binary&ratio=1&rotation=0&showTitle=false&size=233343&status=done&style=none&taskId=u51beb4aa-7251-47eb-b0ae-bca2027d851&title=&width=488)
在 s1 中 创建 sentinel.conf 文件,并添加下面内容

# 哨兵 监听端口,每个哨兵监听一个
port 27001
# 哨兵之间通信使用的ip地址
sentinel announce-ip 192.168.56.103
# 监控集群,格式:sentinel monitor <master name(可自定义)> <master ip> <master port> <quorum>
sentinel monitor mymaster 192.168.56.103 7001 2
# 主观判断指定时间内,节点是否宕机,单位:毫秒
sentinel down-after-milliseconds mymaster 5000
# 故障转移的超时时间,单位:毫秒,如果超时,再选一个slave进行切换
sentinel failover-timeout mymaster 60000
# 工作目录
dir "/root/soft/redis/s1"
# 密码配置,我没有设置密码
#sentinel auth-pass mymaster <password>


# 新的master切换之后,同时有多少个slave被切换到去连接新master,重新做同步
# sentinel parallel-syncs mymaster 1
# 假设1个master,4个slave,然后master宕机了,4个slave中有1个切换成了master,剩下3个slave就要挂到新的master上面去
# 这个时候,如果parallel-syncs是1,那么3个slave,一个一个,排序挂接到新的master上面去
# 如果parallel-syncs是3,那么一次性就会把所有slave挂接到新的master上去

s2、s3类似

启动哨兵:** redis-sentinel s1/sentinel.conf**,启动前要保证redis实例已经启动
![image.png](https://img-blog.csdnimg.cn/img_convert/e02d4cfa83a730d2b5a74731e7bd8eb8.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=258&id=u36ed0311&margin=[object Object]&name=image.png&originHeight=516&originWidth=1726&originalType=binary&ratio=1&rotation=0&showTitle=false&size=494948&status=done&style=none&taskId=ucc729836-0df6-4e0a-8e1e-3abf340d830&title=&width=863)
哨兵启动后,会互相通信
s1
![image.png](https://img-blog.csdnimg.cn/img_convert/941d32b6d52add1d38cd0bfe0ed7b693.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=114&id=u73976916&margin=[object Object]&name=image.png&originHeight=228&originWidth=1728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=257169&status=done&style=none&taskId=u3fa1e433-8bff-4219-b225-73820d535b6&title=&width=864)
s2![image.png](https://img-blog.csdnimg.cn/img_convert/a68f30c1828ce11f9b9853c0b36e9bce.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=87&id=ud62a7312&margin=[object Object]&name=image.png&originHeight=174&originWidth=1666&originalType=binary&ratio=1&rotation=0&showTitle=false&size=246230&status=done&style=none&taskId=u77d26f91-196a-4b68-8677-cbd291588e2&title=&width=833)
s3
![image.png](https://img-blog.csdnimg.cn/img_convert/6e1d6e6a79264e988911cbc8e24782f5.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=87&id=u78ed8be7&margin=[object Object]&name=image.png&originHeight=174&originWidth=1658&originalType=binary&ratio=1&rotation=0&showTitle=false&size=241598&status=done&style=none&taskId=u3bf4afb4-c458-4064-a18a-1bfa230fe77&title=&width=829)

2. 测试

关闭 7001 主节点,从 3 个哨兵日志中,找到如下日志,我的是在s2中找到的
![image.png](https://img-blog.csdnimg.cn/img_convert/df83ee2144bacc693e8532df413c84e7.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=590&id=ud691560f&margin=[object Object]&name=image.png&originHeight=1180&originWidth=2104&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1713363&status=done&style=none&taskId=u5d04fcd8-2009-4cb9-b686-81132088c60&title=&width=1052)
解释:

                                    主观认为 7001 宕机
24701:X 18 Apr 2022 22:48:18.502 # +sdown master mymaster 192.168.56.103 7001 
                                    客观认为 7001 宕机, 因为 quorum 2/2
24701:X 18 Apr 2022 22:48:18.603 # +odown master mymaster 192.168.56.103 7001 #quorum 2/2
                                    开始投票选出一个哨兵做故障转移,最终结果投票给 f5296605b9c786e377e4afb2fb93ded6094415e5
24701:X 18 Apr 2022 22:48:18.603 # +new-epoch 1
24701:X 18 Apr 2022 22:48:18.603 # +try-failover master mymaster 192.168.56.103 7001
                                    投票选出一个哨兵做故障转移
24701:X 18 Apr 2022 22:48:18.608 # +vote-for-leader f5296605b9c786e377e4afb2fb93ded6094415e5 1
24701:X 18 Apr 2022 22:48:18.617 # bf82c362a5d426a822d34327d5d1641683d683bc voted for f5296605b9c786e377e4afb2fb93ded6094415e5 1
24701:X 18 Apr 2022 22:48:18.618 # ed6cbda34457bf8d1f6e910e03362c6062a35061 voted for f5296605b9c786e377e4afb2fb93ded6094415e5 1
24701:X 18 Apr 2022 22:48:18.666 # +selected-leader master mymaster 192.168.56.103 7001
24701:X 18 Apr 2022 22:48:18.666 # +failover-state-select-slave master mymaster 192.168.56.103 7001                       
                                    从集群中选择一个作为新的master,最终选择了 7002
24701:X 18 Apr 2022 22:48:18.721 # +selected-slave slave 192.168.56.103:7002 192.168.56.103 7002 @ mymaster 192.168.56.103 70017002 发送了noone命令,让它成为主节点,查看下方图1
24701:X 18 Apr 2022 22:48:18.721 * +failover-state-send-slaveof-noone slave 192.168.56.103:7002 192.168.56.103 7002 @ mymaster 192.168.56.103 7001
                                    等待其他的sentinel确认
24701:X 18 Apr 2022 22:48:18.798 * +failover-state-wait-promotion slave 192.168.56.103:7002 192.168.56.103 7002 @ mymaster 192.168.56.103 7001
                                    确认完成
24701:X 18 Apr 2022 22:48:19.719 # +promoted-slave slave 192.168.56.103:7002 192.168.56.103 7002 @ mymaster 192.168.56.103 7001
                                    重新配置7001,让其成为slave
24701:X 18 Apr 2022 22:48:19.719 # +failover-state-reconf-slaves master mymaster 192.168.56.103 7001
                                    通知7003 ,新的master是7002,查看下方图2
24701:X 18 Apr 2022 22:48:19.777 * +slave-reconf-sent slave 192.168.56.103:7003 192.168.56.103 7003 @ mymaster 192.168.56.103 7001
24701:X 18 Apr 2022 22:48:20.724 * +slave-reconf-inprog slave 192.168.56.103:7003 192.168.56.103 7003 @ mymaster 192.168.56.103 7001
24701:X 18 Apr 2022 22:48:20.724 * +slave-reconf-done slave 192.168.56.103:7003 192.168.56.103 7003 @ mymaster 192.168.56.103 7001
24701:X 18 Apr 2022 22:48:20.796 # -odown master mymaster 192.168.56.103 7001
24701:X 18 Apr 2022 22:48:20.796 # +failover-end master mymaster 192.168.56.103 7001         
                                    监控新的master
24701:X 18 Apr 2022 22:48:20.796 # +switch-master mymaster 192.168.56.103 7001 192.168.56.103 7002
                                    700370017002 的slave
24701:X 18 Apr 2022 22:48:20.796 * +slave slave 192.168.56.103:7003 192.168.56.103 7003 @ mymaster 192.168.56.103 7002
24701:X 18 Apr 2022 22:48:20.796 * +slave slave 192.168.56.103:7001 192.168.56.103 7001 @ mymaster 192.168.56.103 7002
24701:X 18 Apr 2022 22:48:25.853 # +sdown slave 192.168.56.103:7001 192.168.56.103 7001 @ mymaster 192.168.56.103 7002

图1:
![image.png](https://img-blog.csdnimg.cn/img_convert/84290eb0c3f6ebb69c76e17aab9cfa27.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=277&id=ua6a8f246&margin=[object Object]&name=image.png&originHeight=554&originWidth=1770&originalType=binary&ratio=1&rotation=0&showTitle=false&size=876192&status=done&style=none&taskId=ub53199f2-77e8-4d1b-a557-38a08cdff65&title=&width=885)
图2:
![image.png](https://img-blog.csdnimg.cn/img_convert/1a50860dd79ad46245675964ceabcbe0.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=298&id=uce4345c4&margin=[object Object]&name=image.png&originHeight=596&originWidth=1826&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1097856&status=done&style=none&taskId=ub9823465-cdd7-4c3c-97af-841ff30b2d3&title=&width=913)

这时候再次重启 7001 ,然后查看7002日志,发现7001请求同步数据
![image.png](https://img-blog.csdnimg.cn/img_convert/c789406abfe30b124b8c808197d7ccfd.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=233&id=u19e4b9a4&margin=[object Object]&name=image.png&originHeight=466&originWidth=1520&originalType=binary&ratio=1&rotation=0&showTitle=false&size=599450&status=done&style=none&taskId=ucd28efe9-bc27-4da3-988a-3ce954cc87e&title=&width=760)
查看7001日志,作为一个slave,连接7002
![image.png](https://img-blog.csdnimg.cn/img_convert/df47f7693bea7fac4cf319b7036becca.png#clientId=u86a3d8a6-fb73-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=334&id=u654e0aae&margin=[object Object]&name=image.png&originHeight=668&originWidth=1570&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1067775&status=done&style=none&taskId=ubf310714-e537-4630-a15a-a763add2758&title=&width=785)

4. redisTemplate

1. 创建一个普通的maven项目

![image.png](https://img-blog.csdnimg.cn/img_convert/a943024c57c4acf5ee51253f09b153ac.png#clientId=uf857f37c-a264-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=679&id=u870ffe78&margin=[object Object]&name=image.png&originHeight=849&originWidth=1475&originalType=binary&ratio=1&rotation=0&showTitle=false&size=122427&status=done&style=none&taskId=u9d895351-be71-462c-b8b3-1b196a9ef1f&title=&width=1180)
![image.png](https://img-blog.csdnimg.cn/img_convert/fd50b7aac1dbd6c929cb46197b15e834.png#clientId=uf857f37c-a264-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=679&id=u3bf5bf2b&margin=[object Object]&name=image.png&originHeight=849&originWidth=1475&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33147&status=done&style=none&taskId=u1ebf5084-4175-47e2-9147-4246fd06191&title=&width=1180)

2. pom.xml

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.3.12.RELEASE</version>
</parent>

<dependencies>
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.2</version>
  </dependency>
  <!-- spring data redis 测试 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

  <!-- spring boot 测试 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>

3. 启动类

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

4. properties

# master 名称
spring.redis.sentinel.master=mymaster
# 哨兵地址
spring.redis.sentinel.nodes[0]=192.168.56.105:27001
spring.redis.sentinel.nodes[1]=192.168.56.105:27002
spring.redis.sentinel.nodes[2]=192.168.56.105:27003

5. 配置类

@Configuration
public class RedisConfig {
    
    /**
    * 配置读写分离
    * @return
    */
    @Bean
    public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
        return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }
}

代码中的 ReadFrom._REPLICA_PREFERRED _是redis的读取策略,有下面几种

  • MASTER 从master读取
  • MASTER_PREFERRED 优先 master 读取,master不可用,读 slave
  • REPLICA 从 slave 读取
  • REPLICA_PREFERRED 优先从 slave 读取,slave不可用,读master

6. Controller

@RestController
public class RedisController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/set")
    public String set(@RequestParam String key , @RequestParam String value){
        stringRedisTemplate.opsForValue().set(key, value);
        return "success";
    }

    @GetMapping("/get")
    public String get(@RequestParam String key){
        return stringRedisTemplate.opsForValue().get(key);
    }
}

正常访问,没问题,如果停掉Redis Master 节点,再次访问,也是正常的

5. 两种数据丢失

  • 异步复制导致的数据丢失
    • 因为master -> slave的复制是异步的,所以可能有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了
  • 脑裂导致的数据丢失
    • 脑裂,也就是说,某个master所在机器突然脱离了正常的网络,跟其他slave机器不能连接,但是实际上master还运行着
    • 此时哨兵可能就会认为master宕机了,然后开启选举,将其他slave切换成了master
    • 这个时候,集群里就会有两个master,也就是所谓的脑裂
    • 虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还继续写向旧master的数据可能也丢失了

优化,redis.conf中有两个配置:

  • min-replicas-to-write 1
    • 写数据时,如果跟 master 正常同步的 slave 数量小于1,则 master 拒绝写入
    • 配置0,则关闭此功能
  • min-slaves-max-lag 10
    • 主从库间进行数据复制时,从库给主库发送 ACK 消息的最大延迟,单位:秒
    • 如果大于10秒,则 master 拒绝写入

这两个配置可以有效避免数据的丢失

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值