Redis分布式缓存

文章目录

  • 一、 概述
    • 1. 单节点Redis存在的问题
    • 2. 单节点Redis问题针对解决方案
  • 二、Redis持久化
    • 1. RDB持久化
    • 2.RDB异步持久化原理介绍
    • 3. AOF持久化
    • 4. ROB和AOF对比
  • 三、Redis主从架构
    • 1. 搭建主从架构
    • 2. 主从数据同步原理
  • 四、Redis哨兵
    • 1. 哨兵的作用和原理
    • 2.搭建哨兵集群
    • 3. RedisTemplate的哨兵模式
  • 五、Redis分片集群
    • 1. 搭建分片集群
    • 2. 散列插槽
    • 3. 集群伸缩
    • 4. 故障转移
    • 5. RedisTemplate访问分片集群

一、 概述

1. 单节点Redis存在的问题

  • 数据丢失问题:Redis是基于内存存储的,服务进行重启后容易发生数据丢失问题
  • 并发能力问题:单节点Redis在实际业务中很难处理高并发的场景
  • 故障恢复问题:Redis一旦出现故障对整个服务的影响是致命的,所以要保证Redis是时刻可用的
  • 存储能力问题:内存的有限容量觉得了单节点redis的存储能力是极其有限的,单节点redis很难满足海量数据存储

2. 单节点Redis问题针对解决方案

  • 针对数据丢失问题—实现Redis数据的持久化
  • 针对并发能力问题—搭建Redis集群,实现读写业务的分离
  • 针对存储能力问题—搭建分片集群(类似于ElasticSearch),利用插槽机制实现动态扩容
  • 针对故障恢复问题—利用Redis的哨兵机制,实现对Redis实时健康检测和自动恢复
    下面针对这四个方面逐一介绍

二、Redis持久化

1. RDB持久化

RDB(Redi Database file-redis数据备份文件),也叫做Redis数据快照,利用快照技术,将内存快照记录到磁盘中。当Redis出现故障后,可以从磁盘中的快照快速恢复到出现故障前的状态。(快照文件就是RDB文件,默认保存在Redis当前运行目录)
Redis使用save命令,保存当前内存快照,注意save命令是Redis主进程来实现的,而Redis本身又是单线程的,所以在执行Sava命令时,其它所有的命令都会进入阻塞状态,所以这种方式消耗是非常大的,所以推荐使用bgsave命令,bgsave命令痛殴开辟另外的子线程来执行RDB,而不会影响到Redis主进程,所以性能会更高。最后Redis在关闭前会自动执行一次RDB
测试

  • 启动Redis服务
redis-server 

在这里插入图片描述

  • 退出redis服务

会发现redis自动做了一个RDB

同时也可以在当前运行文件中也可以查看到redis的快照
在这里插入图片描述
总结:我们可以看出Redis在退出服务会自动做一次RDB,而我们的需求时在Redis运行过程中(毕竟实际业务中redis一般不会退出)做数据持久化(以预防服务器出现宕机等情况),实际上Redis内部有触发RDB的机制,可以在redis.conf中进行配置,格式如下:

save 900 1 #900s内,如果至少有一个key被修改,则执行bgsave,如果是sava “” 则表示禁用RDB
save 300 1 #300s内,如果至少有一个key被修改,则执行bgsave,如果是sava “” 则表示禁用RDB
save 60 10000 #60s内,如果至少有一万个key被修改,则执行bgsave,如果是sava “” 则表示禁用RDB

RDB其它配置也可以在Redis.conf文件中设置

rdbcompression yes #是否压缩,建议不开启,压缩会消耗cpu资源
dbfilename dump.rdb #RDB文件名
dir ./ #文件保存的路径目录

测试

  1. 按照配置文件方式启动redis
redis-server /usr/local/redis-6.2.5/redis.conf
  1. 连接redic-cli加入一条新的数据

在这里插入图片描述

2.RDB异步持久化原理介绍

前面我们知道bgsave是主线程fork出来的子进程来执行数据持久化,下面我细化其持久化过程:

  1. 主进程fork一个bgsave进程(这部分主进程会阻塞但时间很短)
  2. 子进程共享主进程的内存资源(包括页表等资源),完成fork后读取内存数据并写入RDB文件
  3. 完成一步异步持久化过程

在这里插入图片描述

问题:由于fork了一个bgsave进程,现在就会引入多线程中的问题,思考如果子线程在读数据的同时主线程又在写数据,这种情况下就可能出现脏读的问题,而redis采用的解决方案是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存
  • 当主线程执行写操作时,则会拷贝一份数据执行写操作

总结:RDB缺点

  • 数据安全漏洞:RDB执行间隔长(我们通过save 60 1可以设置,设置太短RDB次数太多,cpu性能下降),两次间隔之间主线程向Redis中写入数据存在数据丢失的风险
  • forks子进程、压缩(可关闭)、写RDB文件到磁盘都比较耗时

3. AOF持久化

AOF(Append Only File-追加文件):Redis处理的每一个命令都会记录在AOF文件,可以看作是命令日志文件

在这里插入图片描述
AOF数据持久化的原理就是,在Redis接收到的每一条命令都会有序的保存到一个AOF文件中,一旦服务器宕机数据丢失,我们只需要重新执行之前的命令就可以达到恢复数据的效果。在Redis中,AOF是默认关闭的,需要修改redis.conf配置文件来开启AOF

appendonly yes #是否开启AOF功能,默认是no
appendfilename "appendonly.aof #AOF文件名

AOF的命令记录的频率也可以通过redis.conf来配置

appendfsync always #表示每执行一条写命令,立即记录AOF文件(同步刷盘-可靠性高,几乎不丢失数据-性能差)
appendfsync eveysec #写命令执行完放入AOF缓冲区,然后表示每隔一秒将缓冲区数据写入AOF文件,是默认方案(每秒刷盘-性能适中-最多丢失1s数据)
appendfsync no #写命令执行完放入AOF缓冲区,由操作系统觉得何时将缓冲区内容写入磁盘(操作系统控制-性能最好-可靠性差,可能丢失大量数据)

测试

  1. 在配置文件中AOF进行配置,并重启redis
save ""   #禁用rdb
appendonly yes
  1. 向redis中插入数据
set jack chai

出现aof文件(里面记录了写命令)
在这里插入图片描述
3. 重启redis并发现可以看到刚刚插入的数据,说明数据持久化成功
在这里插入图片描述
问题:设想一下这种常见,我对redis中key为jack的数据又进行了多次set赋值操作,此时AOF会将所有set都记录下来,事实上我们知道,set只有最后一次是有意义的,这就导致了AOF记录了很多无效的指令,所以一般AOF会比RDB大的多。而redis是通过bgrewirteaof(它与主线程也是异步的)来解决这个问题的,该命令可以让AOF文件执行重写功能,用最少的命令达到相同效果。

在这里插入图片描述
测试
1.多次set jack值查看aof文件

在这里插入图片描述
2.使用bgrewirteaof重写aof文件,查看效果(BGREWRITEAOF对aof进行了特殊编码)

BGREWRITEAOF

在这里插入图片描述
问题:什么时候触发写AOF文件,前面在介绍RDB持久化方案时,我们知道RDB的执行时间可以时Redis退出时自动执行,或者在通过在配置文件中配置save命令来执行RDB操作。而AOF在Redis中会触发一个阈值区执行操作,阈值同样可以在redis.conf中配置:

auto-aof-rewrite-percentage 100 #AOF文件比上次文件增长超过多少百分比则触发重写
auto-aof-rewrite-min-size 64mb #AOF文件体积最小多大以上才触发重写

4. ROB和AOF对比

RDBAOF
持久化方式定时对整个内存做快照记录每一次执行的命令
数据完整性不完整,两次备份之间会丢失相对完整,取决于刷盘策略
文件大小会有压缩,文件体积小记录命令,文件体积很大
宕机恢复速度很快
数据恢复速度低,因为数据完整性不如AOF高,因为数据完整性更高
系统资源占用高,大量CPU和内存消耗低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源
使用场景可以容忍数分钟的数据丢失,追求更快的启动速度对数据安全性要求较高常见

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者使用

三、Redis主从架构

1. 搭建主从架构

前面说到单节点的Redis并发能力是有限的,要进一步提高Redis的并发能力,需要搭建Redis主从集群,实现读写业务分离。
IMG_352E495EB1A6-1
搭建Redis集群实战

  • 基本描述

集群共包括三个Redis节点,一个主节点,两个从节点(由于资源有限,我这里在一台centos7中搭建三个redis服务,分别开启三个不同的端口来模拟)

  • 创建目录
cd /tmp
mkdir 7011 7012 7013 #分别对应每个redis服务的端口号

在这里插入图片描述

  • 拷贝配置文件(redis.conf)到每个实例目录(上面创建的目录)

这里我这台centos 7中已经安装了一个redis服务,所以我直接拷贝其配置文件即可

cp redis.conf /tmp/7011
cp redis.conf /tmp/7012
cp redis.conf /tmp/7013
  • 修改每个实例的端口、工作目录

修改每个文件夹的配置文件,将端口修改为7001、7002、7003,将rdb文件保存位置都修改为自己所在的目录

sed -i -e 's/6379/7011/g' --e 's/dir .\//dir \/tmp\/7011\//g' 7011/redis.conf
sed -i -e 's/6379/7012/g' --e 's/dir .\//dir \/tmp\/7012\//g' 7012/redis.conf
sed -i -e 's/6379/7013/g' --e 's/dir .\//dir \/tmp\/7013\//g' 7013/redis.conf

其实上面的命令就是执行了文本中指定内容的替换

  • 修改每个实例的声明IP
    虚拟机本身有多个IP地址,未来避免将来发生混乱,需要在redis.conf中指定一个实例的绑定ip信息,格式如下:
replica-announce-ip 172.16.23.146 #这是我虚拟机的ip地址
sed -i '1a replica-announce-ip 172.16.23.146' 7011/redis.conf #1a表示在配置文件第一行后面追加一行
sed -i '1a replica-announce-ip 172.16.23.146' 7012/redis.conf
sed -i '1a replica-announce-ip 172.16.23.146' 7013/redis.conf
  • 启动三个redis服务
redis-server 7011/redis.conf
redis-server 7012/redis.conf
redis-server 7013/redis.conf
  • 查看端口运行情况
netstat -tnlp | grep :70

在这里插入图片描述

  • 开启redis主从关系

上面已经准备好了三个redis服务,但现在这三个服务没有任何关系,要配置主从可以使用replicaof或者slaveof(5.0以前)命令,而主从关系存在着两种模式:

  1. 修改配置文件永久生效: 在redis.conf中添加一行配置slaveof<masterip> <masterport>
  2. 使用redis-cli客户端连接到redis服务,执行slaveof命令slaveof <masterip><masterport>(重启后生效)

(1) 模式二演示:

redis-cli -p 7012  -a 123321  #用密码的形式连接到7012端口
slaveof 172.16.23.146 7011  #添加从属关系

注意如果你的主节点设置了密码的话要给每个从节点授权密码,具体方法是在从节点的配置文件中添加如下命令(不然可能连接不上):

masterauth *****

在这里插入图片描述
其它一台机器同理(这里将7011作为了master主机)
查看集群状态

INFO replication

在这里插入图片描述
测试集群
我现在主节点中添加一条num :1 的数据,看从节点是否可以访问到
在这里插入图片描述
发现访问成功,说明主节点的数据已经成功拷贝到从节点上
(2)模式一只是将slaveof信息写入了配置文件中(从节点的),只需要向配置文件中添加下面的命令,然后重启从节点即可,这里就不操作了:

replicaof 127.0.0.1 7011
masterauth 123321

2. 主从数据同步原理

在上面已经完成了一个简单的redis集群了,也成功测试了从主节点添加信息并从节点可以读到信息了(注意在集群中只有主节点可以写入数据,从节点只能读数据,redis集群默认实现了读写分离业务),下面来分析一下主从数据同步的原理所在:

  • 主从第一次同步是全量同步
    在这里插入图片描述

思考:master如何知道slave是不是第一次来?
这里就要介绍两个重要概念:

  1. Replication ID:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  2. offset:偏移量,随着记录在real_backlog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新

因此slave做数据同步时,必须向master声明自己的Replication IDoffset,master才可以判断到底需要同步哪些数据
总结:全量同步流程

  1. slave节点请求增量同步
  2. maste节点判断replid,发现不一致,拒绝增量同步
  3. master节点将完整内存数据生成RDB,发送RDB到 slave
  4. slave清空本地数据,加载master的RDB
  5. master将RDB期间的命令记录在repl_backlog中,并持续将log中的命令发送给slave
  6. slave执行接收到的命令,保存于master之间的同步
  • 如果slave重启后同步,则执行增量同步

在这里插入图片描述
注意:repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间太久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步。

可以从以下几个方面来优化redis主从集群:

  1. 在master中配置repl-diskless-sync yes启动无磁盘复制,避免全量同步时的磁盘IO(前面说到全量同步时是生产RDB文件后保留到磁盘,然后从磁盘读取发送给slave,而这条命令是直接将RDB文件通过网络的IO发送给slave而不保存到磁盘中,适合网络带宽很多的情况)
  2. Redis单节点上的内存占用不要太大(这样就会减少RDB传输的数据量),减少RDB导致的过多磁盘IO
  3. 以上是全量同步的优化方法,但在实际业务中还是要减少全量同步的次数,所以我们可以提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  4. 限制一个master上的slave节点数量(从节点多了,主节点做数据同步的压力是很大的),入够实战太多slave,则可以采用主-从-从的链式结构(分担部分节点给从节点做从节点,让部分从节点承当数据同步压力),减少master的压力

四、Redis哨兵

思考:slave节点宕机恢复后可以找master节点同步数据,那master节点宕机了怎么办?
解决方案:我们可以对集群状态实时进行监控,当master宕机后我们可以立即找一个从节点来作为新的主节点(主从替换操作),而这个监控任务就交到了Redis哨兵手里

1. 哨兵的作用和原理

Redis提供了哨兵(Sentinel)机制来实现主从几圈的自动故障恢复。哨兵的结构和作用如下:

  • 监控:Sentinel会不断检查你的master和slave是否按照预期工作
  • 自动故障恢复:如果master故障,sentinel会将一个slave提升为master。当故障节点恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给redis客户端

在这里插入图片描述
问题:sentinel是如何监控服务状态的?
sentinel其实是基于心跳机制监控服务状态的,每隔1s向集群的每个实例发送ping命令(和nacos的原理类似):

  • 主观下线:如果某sentinel节点发现某节点未在规定时间响应,则认为该节点主观下线
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该节点主观下线,则该节点客观下线。quorum数量最好超过sentinel集群中的一半

问题:如果选举新的master?
一旦发现master故障,sentinel需要在slave中选择一个新的作为master节点,依据如下:

  • 首先会判断slave节点与master节点断开时间的长短,如果超过指定值(down-after-milliseconds*10—配置文件可以配置),则会排序该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永远不参与选举
  • 如果slave-priority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  • 最后判断slave节点的运行id大小,越小优先级越高(这里相当于随便选一个)

问题:选中slave后如何做故障转移?
当选中一个slave后,故障转移的步骤如下:

  • sentinal给备选的slave发送slaveof no one命令,让该节点称为master
  • sentinal给其它slave发送slaveof (slave的ip地址和端口)命令,让这些slave成为新的master的从节点,开始新的master上同步数据
  • 最后sentinal会将故障节点标记为从节点,当故障节点重启后会成为新的master的从节点

2.搭建哨兵集群

说明:这里在之前搭建的集群的基础上搭建哨兵集群,这里我们搭建一个三个节点组成的sentinel集群,来监管Redis集群

  • 准备实例和配置
  1. 创建文件夹
cd /tmp
mkdir s1 s2 s3
  1. 在每个目录下创建一个sentinal.conf文件,添加如下内容(内容要调整):
touch sentinal.conf #创建文件
#################################
#sentinel monitor mymaster 127.0.0.1 7011 2:监控名为mymaster的主节点,主节点地址为127.0.0.1,端口号为7011,至少需要2个哨兵同意主节点不可用。
sentinel monitor mymaster 172.16.23.146 7011 2 
#主节点的密码(注意从节点的密码要和主节点保持一致)
sentinel auth-pass mymaster  123321
#sentinel down-after-milliseconds mymaster 5000:如果在5000毫秒内无法与主节点建立连接,Sentinel将标记该主节点为不可用。
sentinel down-after-milliseconds mymaster 5000
#sentinel failover-timeout mymaster 30000:故障切换的超时时间为30秒。
sentinel failover-timeout mymaster 30000
#在故障切换期间,每个从节点只能与新的主节点同步一次。
sentinel parallel-syncs mymaster 1
port 27001
#logfile "/var/log/redis/sentinel_27001.log":Sentinel实例的日志文件
logfile "/tmp/s1/sentinel.log"
dir "/tmp/s1"#Sentinel实例的工作目录。
  1. 启动集群
    打开三个控制台分别执行以下命令启动sentinel服务
redis-sentinel s1/sentinel.conf
redis-sentinel s2/sentinel.conf
redis-sentinel s3/sentinel.conf

在这里插入图片描述

  1. 测试效果:让主节点宕机查看sentinel日志文件
  • 连接7011控制台,关闭redis服务
 shutdown

在这里插入图片描述

  • 查看sentinel日志
#sdown表示主观下线
6531:X 31 Mar 2023 19:02:40.992 # +sdown master mymaster 127.0.0.1 7011
#当odown客观下线
6531:X 31 Mar 2023 19:02:41.070 # +odown master mymaster 127.0.0.1 7011 #quorum 2/2
6531:X 31 Mar 2023 19:02:41.070 # +new-epoch 1
6531:X 31 Mar 2023 19:02:41.070 # +try-failover master mymaster 127.0.0.1 7011
#vote-for-leader,选主节点
6531:X 31 Mar 2023 19:02:41.071 # +vote-for-leader bfb12a5712f4dc8bee97ac10ba963ba47fc70c78 1
6531:X 31 Mar 2023 19:02:41.073 # 20134ef7d28b05a8a0c4b8ac0dfef38b09d98bc3 voted for bfb12a5712f4dc8bee97ac10ba963ba47fc70c78 1
6531:X 31 Mar 2023 19:02:41.133 # +elected-leader master mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:41.133 # +failover-state-select-slave master mymaster 127.0.0.1 7011
#7012被选为主节点
6531:X 31 Mar 2023 19:02:41.234 # +selected-slave slave 172.16.23.146:7012 172.16.23.146 7012 @ mymaster 127.0.0.1 7011
#发送slaveof-noone命令给7012
6531:X 31 Mar 2023 19:02:41.235 * +failover-state-send-slaveof-noone slave 172.16.23.146:7012 172.16.23.146 7012 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:41.301 * +failover-state-wait-promotion slave 172.16.23.146:7012 172.16.23.146 7012 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:42.081 # +promoted-slave slave 172.16.23.146:7012 172.16.23.146 7012 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:42.081 # +failover-state-reconf-slaves master mymaster 127.0.0.1 7011
#广播消息
6531:X 31 Mar 2023 19:02:42.150 * +slave-reconf-sent slave 172.16.23.146:7013 172.16.23.146 7013 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:43.158 * +slave-reconf-inprog slave 172.16.23.146:7013 172.16.23.146 7013 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:43.159 * +slave-reconf-done slave 172.16.23.146:7013 172.16.23.146 7013 @ mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:43.213 # -odown master mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:43.214 # +failover-end master mymaster 127.0.0.1 7011
6531:X 31 Mar 2023 19:02:43.214 # +switch-master mymaster 127.0.0.1 7011 172.16.23.146 7012
6531:X 31 Mar 2023 19:02:43.214 * +slave slave 172.16.23.146:7013 172.16.23.146 7013 @ mymaster 172.16.23.146 7012
6531:X 31 Mar 2023 19:02:43.214 * +slave slave 127.0.0.1:7011 127.0.0.1 7011 @ mymaster 172.16.23.146 7012

从上面日志文件中可以看出sentinel的故障处理的过程,同时我们可以进入7012的控制台看现在的集群状况
在这里插入图片描述
现在恢复之前宕机的主节点,查看是否会变成从节点,下面进入7011后,执行set num2 1命令发现已经没有权限了
在这里插入图片描述

3. RedisTemplate的哨兵模式

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化(前面已经演示)及时更新链接信息。Spring的RedisTemplate底层利用lettuce实现李节点的感知和自动切换。

Lettuce 是一个高级 Java Redis 客户端,它提供了基于 Java NIO(非阻塞 I/O)的连接和编码基础设施。在 Spring 应用程序中,Lettuce 通常被用作 Redis 的底层客户端库,与 Spring Data Redis 集成,以提供对 Redis 数据结构、缓存和其他功能的支持。

下面在idea中进行测试

  1. 新建一个SpringBoot项目(很简单这里就不演示了)
  2. 在pom文件中引入redis的starter的依赖
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
  1. 在application.yml中指定sentinel的相关信息
logging:
  level:
    io.lettuce.core: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
spring:
  redis:
    sentinel:
      master: mymaster   #指定主节点
      nodes: #指定redis-sentinal集群信息
        - 172.16.23.146:27001
        - 172.16.23.146:27002
        - 172.16.23.146:27003
    password: 123321 #redis密码
  1. 配置主从读写分离(主负责写,从负责读)
   @Bean
    public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomize(){
    //对lettuce的自定义配置
      return  clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }

这里的ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave(replica)节点读取
  • REPLICA_PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

我们现在就可以在日志中读取关于Redis集群的相关信息了

在这里插入图片描述

五、Redis分片集群

问题:前面介绍了主从以及哨兵可以解决高可用、高并发读写问题,但是依然有两个问题没有解决:

  1. 海量数据存储问题
  2. 高并发写的问题

使用分片集群可以解决上述问题,分片集群特征:

  1. 集群中有多个master节点,每个master保存不同的数据(所以数据存储的上限变为了master数量)
  2. 每个master都可以有多个slave节点
  3. master之间通过ping检测彼此健康状态(不需要哨兵了)
  4. 客户端请求可以访问集群任意节点,最终都会转发到正确节点
    在这里插入图片描述

1. 搭建分片集群

分片集群需要的节点数量比较多,这里我们搭建一个最小的分片集群,保护3个master节点,每个master节点保护一个slave节点。

  • 准备实例和配置
  1. 创建目录
mkdir 7001 7002 7003 8001 8002 8003
  1. 在tmp下创建一个redis.conf文件,文件内容如下
port 6379
# 开启集群功能
cluster-enabled yes
#集群的配置文件名称,不需要我们自己创建,由redis自己维护(这是个只读文件)
cluster-config-file /tmp/6379/nodes.conf
#节点心跳失败的超时时间
cluster-node-timeout 5000
#持久化文件存放目录
dir /tmp/6379
#绑定地址
bind 0.0.0.0
#让redis后台运行
daemonize yes
#主从的实例ip
replica-announce-ip 172.16.23.146
#保护模式
protected-mode no
#数据库数量
datebases 1
#日志
logfile /tmp/6379/run.log 
  1. 将文件拷贝到每个目录中
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf #管道

在这里插入图片描述
4. 修改每个文档下conf文件的内容

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
  • 启动
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
  • 查看运行结果
    在这里插入图片描述

关闭所有进程用这种方式:

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown
  • 创建集群

这里我用的redis 6所有用的5.0之后版本的创建方式,5.0之前有别的创建方式

redis-cli --cluster create --cluster-replicas 1 172.16.23.146:7001 172.16.23.146:7002 172.16.23.146:7003 172.16.23.146:8001 172.16.23.146:8002 172.16.23.146:8003

redis-cli --cluster:代表集群操作命令
create:表示创建集群
--cluster-replicas:指定集群中每个master的副本的个数为1,此时节点总数/(replicas+1)得到的是master的数量。因此节点列表中的前n个是master,其它节点都是slave节点,随机分配到不同master

在这里插入图片描述

  • 查看集群状态
redis-cli -p 7001 cluster nodes

在这里插入图片描述

集群搭建就完成了

2. 散列插槽

前面我们创建集群的过程中会看到散列插槽的分配情况如下:
在这里插入图片描述

redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,为什么要插槽

思考当我们需要向redis中插入数据的时候,数据该插到哪里,这其实是和插槽有关的(数据和插槽绑定,就不会因为节点的宕机而数据发生丢失了)!

数据的key不是和节点绑定的,而是和插槽绑定的,redis会根据key的有效部分计算插槽值,分两种情况:

  1. key中包含"{}“中至少一个字符,”{}"中的部分是有效部分
  2. key中不包含"{}",整个key都是有效部分

eg:key是num,那么根据num计算,如果是{jakie}num,则根据jakie计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值

  • 测试

(1) 连接一个master节点

 redis-cli -c -p 7001 #-c表示集群模式

(2) 加入数据
在这里插入图片描述
(3) 结论:redis分片集群操作数据的过程:

  1. 根据key利用hash算法计算key值,即插槽值
  2. 根据插槽值找到对应插槽的节点
  3. 重定向到相应的节点,对数据进行操作

思考如何将同一类数据固定保存到一个redis实例(节点)?

利用前面介绍到 的{}机制

3. 集群伸缩

集群的伸缩功能是指实现集群的动态增加或移除节点

add-node new_host:new_port existing_host:existing_port
         --cluster-slave #不指定默认添加是主节点
         --cluster-master-id <arg>

案例:向集群中添加一个新的master节点,并向其存储num=10

  • 启动一个细腻的redis,端口为7004
  • 添加7004到之前的集群,并作为一个master节点
  • 给7004节点分配插槽,使得num这个key可以存储到7004节点
  1. 创建一个新的节点(和前面的操作一样这里不赘叙了)
  2. 将7004加入到redis集群中的master节点
redis-cli --cluster add-node 172.16.23.146:7004 172.16.23.146:7001 

在这里插入图片描述
3. 给7004分配指定的插槽
在这里插入图片描述

redis-cli --cluster reshard 172.16.23.146:7001

在这里插入图片描述
查看插槽分配情况:

redis-cli -p 7001 cluster nodes

在这里插入图片描述
4. 插入数据
在这里插入图片描述

4. 故障转移

虽然分片集群不存在哨兵机制,但是也可以实现故障转移功能。当一个集群的master宕机后,同样会选择一个slave节点来充当主节点,然后宕机的节点恢复后就会成为新的主节点的slave节点,具体的流程如下:

  1. 首先是该节点于其它节点失去连接
  2. 然后是疑似宕机
  3. 最后确定下线,自动提升一个slave为新的master节点

上面上redis自动故障转移的过程
利用cluster failover命令可以实现手动让集群的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移,具体流程如下:
在这里插入图片描述
手动的Failover支持三种不同的模式:

  • 缺省:默认的流程,会执行上面的1-6步
  • force:省略流程中对offset的校验
  • takeover:直接执行第五步,忽略数据的一致性、忽略master状态和其它master的意见

测试:让8001成为master

  1. 利用redis-cli连接这个节点
redis-cli -c -p 8001
  1. 执行cluster failover命令
CLUSTER FAILOVER  #默认执行上面六个流程
  1. 查看结果
redis-cli -p 7001 cluster nodes

在这里插入图片描述

5. RedisTemplate访问分片集群

Redis Template底层同样基于lettuce实现了分片集群的支持,使用的步骤于哨兵模式基本一致,下面简单使用一下

  1. 引入Redis的starter依赖(和哨兵模式一致)
  2. 配置分片集群地址
spring:
  redis:
    cluster:
      nodes: #指定分片集群的每一个节点信息
        - 172.16.23.146:7001
        - 172.16.23.146:7002
        - 172.16.23.146:7003
        - 172.16.23.146:7004
        - 172.16.23.146:8001
        - 172.16.23.146:8002
        - 172.16.23.146:8003

  1. 配置读写分离(和哨兵模式一样)
  2. 查看结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/7769.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 操作系统原理 — RSS 多队列网卡

目录 文章目录目录RSS 多队列网卡RSS 技术实现原理RSS FilterRSS HASH硬中断信号绑定ethtool 操作指令RSS 多队列网卡 在以往&#xff0c;一张 NIC 只具有一个 Rx Queue&#xff0c;对应一个 CPU Core 来进行收包处理。在多核时代&#xff0c;为了充分利用 Multi-CPU Cores&am…

如何使用pandas提取含有指定字符串

这里写自定义目录标题name age state point0 Alice 24 NY 641 Bob 42 CA 922 Charlie 18 CA 70name age state point0 Alice 24 NY 642 Charlie 18 CA 700 False1 True2 TrueName: state, dtype: boolname age state point1 Bob 42 CA 922 Charlie 18 CA 700 True1 False2 True…

tmall.service.settleadjustment.modify( 修改结算调整单 )

&#xffe5;开放平台免费API必须用户授权 提供给服务商在对结算有异议时&#xff0c;发起结算调整单。 通过说明调整单ID&#xff0c;调整费用值&#xff0c;调整原因进行结算调整单修改。 公共参数 请求地址: 公共请求参数: 公共响应参数: 请求参数 响应参数 点击获取key和…

MyBatisPlus-DML编程控制

MyBatisPlus-DML编程控制4&#xff0c;DML编程控制4.1 id生成策略控制知识点1&#xff1a;TableId4.1.1 环境构建4.1.2 代码演示AUTO策略步骤1:设置生成策略为AUTO步骤2:删除测试数据并修改自增值步骤3:运行新增方法INPUT策略步骤1:设置生成策略为INPUT步骤2:添加数据手动设置I…

【hello Linux】Linux权限管理

目录 1.shell命令以及运行原理 2. Linux权限的概念 3. Linux权限管理 3.1 文件访问者的分类 3.2 文件类型 3.3 访问权限 3.4 访问权限的表示方法 4. 访问权限的相关设置 4.1 chmod命令&#xff1a;修改权限 4.2 chown命令&#xff1a;修改文件的拥有者 4.3 chgrp 命令&#xff…

idea中的项目上传gitee

1.把gitee插件安装找重启idea 2.打开gitee网站从设置->私有令牌 获取token信息完成登录 复制到idea中点击log in 点击ok 3.把项目转为git管理 4.上传到gitee 5.去刷新gitee仓库此时就会发现多了一个我们的项目 以下是拷贝新项目到idea操作 http://t.csdn.cn/ycnSX

【Ansys】什么软件模块是DS,它和workbench、mechanical的区别在哪里?

一、DesignSpace和workbench 早期的Workbench称之为DesignSpace&#xff0c;更偏向于建模。 现在DS是license的一种&#xff0c;而分析的模块在11中称之为Simulation&#xff08;Design Simulation&#xff09;&#xff0c;在12中改名为Mechanical。 所以&#xff0c;你可以…

IFPUG功能点度量4:度量事务功能

一、基本概念 1、事务功能 事务功能是处理数据功能的基本过程。 每个事务功能都是一个基本过程。 事务功能由多个逻辑处理来完成。 事务功能包含三种类型&#xff1a;EI、EO、EQ 2、基本过程 一个基本过程是由一个逻辑处理或者多个逻辑处理来完成的。 如何识别&#xf…

【备考技巧】系统集成(案例分析题)并不难

案例分析考题分析&#xff1a; 正常情况下四道题&#xff0c;计算题20分左右&#xff0c;剩余三道分析题每题15-20分左右。 ☆案例分析题&#xff1a; 从整体管理、范围管理、质量管理、人力资源管理、合同管理&采购管理、配置管理、风险管理、进度管理、成本管理中出简答题…

Jvm学习笔记(二)GC

GC 垃圾收集(GC)起源于Lisp&#xff0c;远比Java的历史更久&#xff0c;它主要思考了三件事情&#xff1a; 哪些内存需要回收&#xff1f;什么时候回收&#xff1f;如何回收&#xff1f; 本章就根据这三个点进行分析。 哪些内存需要回收&#xff1f; 在java堆中存放着无数的…

Mac浏览器无法上网但可以用微信等

可以使用微信QQ等&#xff0c;但是浏览器无法上网&#xff0c;Mac浏览器无法上网怎么办&#xff0c;Mac浏览器无法上网但可以用微信等&#xff08;百度了一下&#xff0c;没有找到原因是为什么&#xff0c;只找到了解决方法&#xff0c;记录一下&#xff09; 1.首先我们打开Ma…

Centos安装docker以及通过docker部署Mysql,照做就行!

1.安装docker 1.1给虚拟机联网&#xff08;反斜杠带表该语句没写完&#xff09; yum install -y yum-utils \device-mapper-persistent-data \lvm2 --skip-broken 1.2更新本地文件镜像 # 设置docker镜像源 yum-config-manager \--add-repo \https://mirrors.aliyun.com/doc…

【Python_Selenium学习笔记(四)】基于Selenium模块实现键盘操作

基于Selenium模块实现键盘操作 前言 在 Selenium 模块中&#xff0c;提供了一个 Keys 类&#xff0c;来处理键盘操作&#xff1b; 在 Selenium 模块中&#xff0c;使用 send_keys() 方法&#xff0c;来模拟键盘输入&#xff0c; 此篇文章主要介绍如何使用 Keys 类 和 send_ke…

vue请求本地JSON文件(注意路径 否则会404)

npm i axios // main.jsimport axios from "axios";Vue.prototype.$axios axios; //全局注册&#xff0c;使用方法为:this.$axios...vue/cli 2 json文件存放目录为 根目录下static/json/aaa.json // 使用getVideoData() {this.$axios.create({baseURL: "&quo…

springboot 部署k8s(二)

系列文章目录 目录 系列文章目录 前言 操作步骤 1.springboot.yaml文件 2.查看deployment 3.查看service服务 4.验证服务 总结 前言 springboot 部署到k8s 上。里面涉及了deployment, Service, NodePort. 操作步骤 1.springboot.yaml文件 apiVersion: apps/v1 kind: …

codeblocks20.3配置wxWidget3.2.2.1

codeblocks20.3 # 英文版自带gcc810&#xff0c;不汉化 wxWidget3.2.2.1 github下载源码 win11专业版 1.下载wxWidget3.2.2.1 源码 2.下载后解压到一个目录中&#xff0c;不要含中文和空格。我放在&#xff1a;d:\wxWidget3.2.2.1 3.打开终端cd build/msw 4.编译wxWidgets 为 …

本行卡转账基本流程说明

1、业务大致流程 2、基本业务描述 大概流程说明&#xff1a;&#xff08;牵涉到调用硬件、不便多说&#xff09; 用户插卡后、选择转账交易、依次输入转入账户卡号和转账金额后&#xff0c;用户确定转账信息&#xff1b;转账交易发送前&#xff1a;需要根据插卡账户信息和转账…

Java基础(四)数组

1. 数组的概述 1.1 为什么需要数组 需求分析1&#xff1a; 需要统计某公司50个员工的工资情况&#xff0c;例如计算平均工资、找到最高工资等。用之前知识&#xff0c;首先需要声明50个变量来分别记录每位员工的工资&#xff0c;这样会很麻烦。因此我们可以将所有的数据全部存…

TCP报文 Flood攻击原理与防御方式

TCP交互过程中包含SYN、SYN-ACK、ACK、FIN和RST报文&#xff0c;这几类报文也可能会被攻击者利用&#xff0c;海量的攻击报文会导致被攻击目标系统资源耗尽、网络拥塞&#xff0c;无法正常提供服务。接下来我们介绍几种常见的Flood攻击的原理和防御方式。 SYN Flood攻击与防御…

【Qt】项目开发遇到问题及解决总结

1.控件的触发&#xff1a;toggle()、triggered()、clicked() 区别&#xff1a; 都是按钮点击后发射的信号 clicked()&#xff1a;用于Button发射的信号triggered()&#xff1a;用于QAction发射的信号&#xff0c; trigger是一次性的。 点击后&#xff0c;无法改变状态。 要么…