Redis介绍:
Redis(Remote Dictionary Server,即远程字典服务 ),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。作为一款高性能key-value非关系型(不保证关系数据的ACID特性)内存数据库,提高扩展性和性能的同时,还支持字符串(String),哈希(Hash),列表(list),集合(sets)和有序集合(sorted sets)五种存储类型,弥补了传统内存数据库(如Memcached)的不足。为此,Redis因为高性能,易扩展,数据多样性等优点,目前被广泛应用于多个领域。
Redis号称读每秒11万,写每秒8万次。这些数据由官方redis-benchmark测试所得。
Redis还提供了三种集群方案:主从、哨兵和Redis-Cluster集群。
Redis支持两种持久化方案:RDB(快照)和AOF,默认情况下使用RDB持久化。RDB是将数据库的快照(snapshot)以二进制的方式保存到磁盘中;AOF将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。
RDB还原较快,持久化是通过子进程进行全量操作,对系统资源有额外的要求;宕机时,丢失一部分数据。
AOF只保存写操作指令(每秒保存一次,官方提出性能常可),速度快;但还原需要执行指令,速度慢。AOF文件较大,但支持重写(新的AOF文件);宕机时,最多只丢失1秒数据。
dir "/usr/local/redis/other" #RDB和AOF文件路径
--RDB持久化基本配置-----------------------------------------
dbfilename "dump.rdb" # RDB文件名
# 持久化时机配置,save m n,表示m秒内至少有n个key发生变化,则自动触发rdb持久化
save 3600 1
save 300 100
save 60 10000
--AOF持久化基本配置-----------------------------------------
appendonly no # AOF持久化开关
appendfilename "appendonly.aof" # AOF文件
appendfsync everysec # 持久化时机,有三种选项(no、alway和everysec)
持久化是数据库必不可少的一部分,因为是磁盘IO操作,对性能影响较大,在高并发场合尤为注意。这两种持久化方案,可以单独使用,也可以一起使用。一起使用时,RDB作为容灾备份策略,备份时间间隔较长,还原时候主要使用AOF,因为它是最正确(最多损失1秒数据)。
Redis常见问题:缓存穿透、缓存击穿,缓存雪崩。
缓存穿透:数据未做缓存,请求直达DB(如mysql);
缓存击穿:某热点缓存数据(一个key)失效,请求直达DB;
缓存雪崩:同一时间数据集体失效或者缓存数据库宕机,导致请求直达DB。这种对系统影响最大。
线上场景避免以上三种问题,一般的方案如下:
查询不到的key在缓存数据库设置为NULL,避免请求穿透直达DB;
数据设置为永久,避免击穿;
分散错开设置key的有效期;
数据预热,对已知热点场景提前加载热点数据;
搭建集群,利用集群的高性能高可用特性,避免宕机影响;
限流降级,在合适的时机加锁。大量缓存失效时,进入加锁流程,避免激烈冲击DB;
一、Redis基本安装配置
1.安装包下载:
# 安装包为2021.10.4发行版
wget http://download.redis.io/releases/redis-6.2.6.tar.gz
也可以通过游览器下载: Redis 或 Index of /releases/
2.编译和安装
# 解压
tar zxvf redis-6.2.6.tar.gz
cd redis-6.2.6
# 编译,需要提前安装gcc(yum -y install gcc)
make
#切换目录到src并执行安装,指定安装目录
cd src
make install PREFIX=/usr/local/redis
3.部署
到此,在/usr/local/redis只有一个bin目录,目录内容都是可执行文件:
为了方便管理,我们把用到的配置文件也拷贝一份到/usr/local/redis:
# 创建存放redis配置文件的目录
mkdir -p /usr/local/redis/etc
#把前面解压目录下的配置文件拷贝到安装目录下的etc目录
cp XXX/redis-6.2.6/redis.conf XXX/redis-6.2.6/sentinel.conf /usr/local/redis/etc/
4.Redis的启动格式:/redis-server /path/to/redis.conf,不指定配置文件则使用默认配置。如在/usr/local/redis,执行以下命令管理Redis启停和连接:
# 开启redis服务端
./bin/redis-server ./etc/redis.conf
# 停止redis服务端
./bin/redis-cli shutdown
# 连接redis服务,默认配置且在本机登录redis,不需要ip、端口、用户和密码等信息。也可以进入redis再输入密码(如果设置了密码登录,命令格式:auth password)
./bin/redis-cli [-h hostname -a pwd -p port]
5.为了方便使用redis-cli,通过软链接设置环境变量:
ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis
二、主从模式搭建
Master用于写操作(也可读),Slave用于读操作(不可写)
1.数据同步和新Master选取
正常运行期间通过Master实时推送写备份到slave实现同步。如果Slave宕机或重启,Slave重新向Master发起PSYNC命令,Master根据双方数据的偏差量判断是否是需要完整重同步还是仅将断线期间执行过的写命令发给Slave。
新Master选取逻辑:redis sentinel模式下,如何选举新的master_猿界汪汪队的博客-CSDN博客_redis哨兵模式选举master
2.准备三台机器演示:
192.168.1.14 6379 Master
192.168.1.15 6379 Slave
192.168.1.16 6379 Slave
3.配置
配置文件是/usr/local/redis/etc/redis.conf
先通过命令mkdir -p /usr/local/redis/other创建other目录,用户存放redis数据文件
Master配置:
bind * -::* # 监听可用多路接口(多网卡主机)。也可以指定监听的ip
port 6379
protected-mode no # 非保护模式可接受远程连接
daemonize yes # 守护进程
pidfile "/usr/local/redis/other/redis_6379.pid"
logfile "/usr/local/redis/other/redis_6379.log"
dbfilename "dump_6379.rdb" # rdb存储文件
dir "/usr/local/redis/other" #存储路径
requirepass "123456" # master设置验证密码,所有客户端(包括slave)都需要验证
masterauth "123456" # slave登录master验证密码(即requirepass)
Slave配置:
bind * -::*
port 6379
protected-mode no
daemonize yes
pidfile "/usr/local/redis/other/redis_6379.pid"
logfile "/usr/local/redis/other/redis_6379.log"
dbfilename "dump_6379.rdb"
dir "/usr/local/redis/other"
requirepass "123456" # 由于后面需要搭建容灾,即一个slava实例会切换为master,所以需要保留此配置
masterauth "123456" # slave登录master验证密码(即requirepass)
replicaof 192.168.1.14 6379 # 开放此配置则为slave,通过此配置的ip和port连接master,由master进行数据同步。所以两个slave都一样配置即可。
4.关闭防火墙:
firewall-cmd --add-port=6379/tcp --permanent --zone=public
firewall-cmd --reload
5.重启三个redis实例
cd /usr/local/redis
./bin/redis-cli -a 123456 shutdown
./bin/redis-server ./etc/redis.conf
6.查看Master info信息:当前角色为master,且有两个slave连接:
7.查看Slave info信息:当前角色为slave,并表示master在线而且展示了master的ip和port:
8.主从同步数据验证:
Master:
Slave:
三、哨兵模式搭建(在主从模式基础上搭建)
Redis高可用方案,是通过搭建一个或多个Sentinel实例实现的。它可以监控任意多个Master以及其下属Slave,当监控的Master下线时,自动将该Master下属的某个Slave升级为新Master。
1.配置
配置文件是/usr/local/redis/etc/sentinel.conf
前面用了三台机器搭建三个redis实例。为此,我们在每台机器都搭建一个Sentinel,三个Sentinel的配置一样:
protected-mode no
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel.pid"
logfile "/usr/local/redis/other/sentinel.log"
dir "/tmp" # 哨兵工作目录
sentinel monitor mymaster 192.168.1.14 6379 2 # mymaster是master名,然后是master的ip和port, 最后的2表示只要有2个sentinel认为master失联,那么客观上可以认为master失联
sentinel auth-pass mymaster 123456 # 对应master配置的requirepass
sentinel down-after-milliseconds mymaster 5000 # master回应哨兵最大时间间隔,超时则认为master下线
2.关闭防火墙:
firewall-cmd --add-port=26379/tcp --permanent --zone=public
firewall-cmd --reload
3.启动三个哨兵:
cd /usr/local/redis
./bin/redis-sentinel ./etc/sentinel.conf
# 顺便贴出关闭sentinel命令(此步有需要再操作)
./bin/redis-cli -p 26379 shutdown
4.随便一台机器登录并输入info Sentinel:有详细master信息,包括ip和port、slave和sentinel数量:
# 登录sentinel
./bin/redis-cli -p 26379
5.容灾测试:
1)master所在机器执行关闭redis操作:
./bin/redis-cli -a 123456 shutdown
2)查看到其中一个Slave(192.168.1.16)已经升级为Master,此时另一个Slave已和新的Master连接并同步
3) 尽管旧Master(192.168.1.14)重启,也不会抢占master权限(非抢占式):
切换master后,会同步修改配置内容(包括redis.conf和sentinel.conf) :
所有sentinel.conf更新master的ip和port信息:
新Master的 redis.conf移除replicaof字段配置,其他slave(旧master则上线后操作)更改replicaof字段:
四、Cluster模式搭建(推荐)
Redis哨兵模式实现了高可用,读写分离,但是其主节点仍然只有一个,即写入操作都是在主节点中,这也成为了性能的瓶颈。
因此Redis在3.0后加入了Cluster模式,它采用去无心节点方式实现,集群将会通过分片方式保存数据库中的键值对。Cluster模式下,每个主结点都支持关联从结点,每个结点通过ping相互感应,若判断某个主结点下线,通过raft算法从从结点中选举新的master。可见,Cluster模式同时具备高可用和高性能读写的优点。
1.在同一个机器中搭建6个redis实例,单独创建一个cluster_test目录,并把redis-server和最原始的redis.conf复制到cluster_test目录中,切换到cluster_test目录且创建7000-7005目录:
cd /usr/local/redis
mkdir cluster_test
cp xxx/redis-6.2.6/redis.conf xxx/redis-6.2.6/src/redis-server ./cluster_test
cd cluster_test
mkdir 7000 7001 7002 7003 7004 7005
2.先修改redis.conf:
port 7000
daemonize yes
pidfile /usr/local/redis/cluster_test/7000/redis.pid
logfile "/usr/local/redis/cluster_test/7000/7000.log"
dir /usr/local/redis/cluster_test/7000/
cluster-enabled yes # 开启cluster
cluster-config-file nodes-7000.conf # 用于保存集群结点信息,以便重启时获取
cluster-node-timeout 5000
appendonly yes
3.把redis.conf复制到7000-7005目录,并修改所有配置文件的端口以及使用端口作为样式设置的配置:即修改 port、pidfile、logfile、dir和cluster-config-file 这5个字段配置。
4.启动所有redis实例:
cd /usr/local/redis/cluster_test
# 连续启动6个
./redis-server ./7000/redis.conf
.
.
./redis-server ./7005/redis.conf
5.此时查看集群信息:并没有分配slot,而且结点间也没有相互感知:
注:前面已经在/usr/bin/创建redis-cli的软链接redis,所以可以直接使用redis命令作为客户端操作
6.创建cluster:
# --cluster-replicas 1 : 表示希望每个主结点有一个从结点
redis --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
输入yes接受建议配置
创建成功,最后一条输入日志如下:
7.此时在查看群集信息:
redis -p 7000 cluster info
redis -p 7000 cluster slots
redis -p 7000 cluster nodes
各结点相互感知,而且16384个slot都分配出去,集群信息如下:
7000(master) -- 7004(slave)
7001(master) -- 7005(slave)
7002 (master)-- 7003 (slave)
8.测试:
四(1)Cluster模式 重新分片集群
1.指令格式:
# <host>:<port> : 选择其中一个master的ip和port,他会查找对应结点并处理
# --cluster-from <node-id> : 槽位移除结点,node-id下面介绍如何获取
# --cluster-to <node-id> : 槽位移入结点
# --cluster-slots <number of slots> : 槽位数量
# --cluster-yes : 自动回复交互
redis-cli --cluster reshard <host>:<port> --cluster-from <node-id> --cluster-to <node-id> --cluster-slots <number of slots> --cluster-yes
# node-id 介绍:通过redis -p port cluster nodes查找
2. node-id查找演示
3.重新分片指令示例
# 7000分配1000个slot给7002
redis --cluster reshard 127.0.0.1:7000 --cluster-from bdecd017def519a9bfbb9fd79f77065444d3f971 --cluster-to 0b0f81b05889dbfdba419359d6b9ed44037d6c05 --cluster-slots 1000 --cluster-yes
效果
四(2)Cluster模式 添加Master新节点
1.创建7006目录并且复制一份redis.conf配置,修改端口为7006,并且修改配置相应字段(路径和文件名等,可以参考 Cluster模式搭建 章节)。开启此redis,使用ps查看下:
2.指令
# 增加节点为master结点指令
# 127.0.0.1:7006 为新结点
# 127.0.0.1:7000 为辅助处理指令的结点
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
效果:
但需要注意,此时新master结点7006是没有slot,所以也不参与从结点的选举(即不参与从结点到master的选举)
3.使用前面学习过的 重新分片 给7006分配slots
redis --cluster reshard 127.0.0.1:7000 --cluster-from 0b0f81b05889dbfdba419359d6b9ed44037d6c05 --cluster-to c5f13493eccbb179ab113fa769b645506e58fa01 --cluster-slots 1000 --cluster-yes
效果如下:
四(3)Cluster模式 添加新节点作为副本
1.创建7007目录并且复制一份redis.conf配置,修改端口为7007,并且修改配置相应字段(路径和文件名等,可以参考 Cluster模式搭建 章节)。开启此redis,使用ps查看下:
2.指令演示
# 127.0.0.1:7007 -- 作为新副本结点
# 127.0.0.1:7000 -- 处理指令的结点
# --cluster-slave -- 指示新增加的结点为从结点
# --cluster-master-id node-id -- 为新副本结点的master结点node-id
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id c5f13493eccbb179ab113fa769b645506e58fa01
# node-id 介绍:通过redis -p port cluster nodes查找
效果
四(4)Cluster模式 删除节点
1.指令
# 127.0.0.1:7000 处理指令的结点
# node-id 需要删除的结点id
redis-cli --cluster del-node 127.0.0.1:7000 `<node-id>`
2.删除7007从结点演示
redis-cli --cluster del-node 127.0.0.1:7000 acb4756c61cc33c4b467554d7c70c277f2c08bea
使用redis -p 7000 cluster nodes查看,7007结点已经不存在
但是要注意,如果要删除master结点,需要确保其没有数据。可以通过分片(前面有介绍)功能,先把slot分配到其他master,然后再操作del node。
注:以下操作请到官网学习(参考文献有给出链接)
测试故障转移、手动故障转移、副本迁移、升级Redis集群中的节点、迁移到 Redis 集群
参考文献:
redis学习从练气到化虚_时来天地偕同力,运去英雄不自由-CSDN博客