赞
踩
RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
快照文件称为RDB文件,默认是保存在当前运行目录。
配置文件介绍
## Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下: # 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB save 900 1 save 300 10 save 60 10000 # RDB的其它配置也可以在redis.conf文件中设置: ## 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱 rdbcompression yes ## RDB文件名称 dbfilename dump.rdb ## 文件保存的路径目录 dir ./
命令
## 由redis主进程执行来执行RDB,会阻塞所有命令
save
##bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。
# fork采用的是copy-on-write技术:
# 当主进程执行读操作时,访问共享内存;
# 当主进程执行写操作时,则会拷贝一份数据,执行写操作。
bgsave
RDB方式bgsave的基本流程
RDB会在什么时候执行
save 60 1000代表什么含义
恢复RDB文件
RDB的优点
RDB的缺点
AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。
AOF默认是关闭的,需要修改redis.conf
配置文件来开启AOF
# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
AOF的命令记录的频率也可以通过redis.conf文件来配:
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
配置项 | 刷盘时机 | 优点 | 缺点 |
---|---|---|---|
Always | 同步刷盘 | 可靠性高,几乎不丢数据 | 性能影响大 |
everysec | 每秒刷盘 | 性能适中 | 最多丢失1秒数据 |
no | 操作系统控制 | 性能最好 | 可靠性较差,可能丢失大量数据 |
因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:
## AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
## AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb
AOF优点
AOF缺点
RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。
RDB | AOF | |
---|---|---|
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
宕机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
系统资源占用 | 高,大量CPU和内存消耗 | 低,主要是磁盘IO资源 但AOF重写时会占用大量CPU和内存资源 |
使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
由于 redis 是用 C 语言开发,安装之前必先确认是否安装 gcc 环境(gcc -v),如果没有安装,执行以下命令进行安装
## 下载安装gcc
yum install -y gcc
## 测试gcc版本
gcc --version
方式一:官网下载
官网下载: https://redis.io/
方式二:wget下载
cd /opt/home/
## 下载
wget https://download.redis.io/releases/redis-6.2.6.tar.gz
## 解压
tar -zxvf redis-6.2.6.tar.gz
## 切换目录 执行编译
cd redis-6.2.6/
## 编译安装 如不指定目录 则会默认安装到 /usr/local/bin
make && make install PREFIX=/opt/home/redis
cd /opt/home/redis/bin ## 1.启动Redis ./redis-server # 2.停止redis服务 ./redis-cli shutdown ## 3.后台启动(推荐) # 3.1 从 redis 的源码目录中复制 redis.conf 到 redis 的安装目录 cp /opt/home/redis-6.2.6/redis.conf /opt/home/redis/bin ## 3.2 修改配置 vi redis.conf ####修改内容如下##### ## 远程访问 # 注释掉: bind 127.0.0.1 -::1 ## 后台启动 #daemonize no 改为daemonize yes ## 设置密码: # 取消注释:requirepass foobared # 应修改为:requirepass java521 ## 修改rdb文件存放路径 # 将 ./ 修改为/opt/home/redis/bin/ dir /opt/home/redis/bin/ ## redis 日志文件路径 logfile "/opt/home/redis/bin/redis.log" ## 484行 当master服务设置了密码保护时 slave服务连接master的密码 # masterauth <master-password> masterauth java521 ## 3.3 执行启动命令指定配置文件就是后台启动了 ./redis-server redis.conf ## 4.查看是否启动 ps -aux | grep redis ## 5 关闭redis服务 # 5.1 末设密码 ./redis-cli shutdown # 5.2 设置了密码 ./redis-cli -a java521 shutdown
./redis-cli ## 设置密码后访问需要先输⼊密码认证通过 # auth 检测给定的密码和配置文件中的密码是否相符 auth java521 ## 查看所有的key keys * ## 设置指定 key 的值 set k1 v1 ## 获取指定 key 的值 get k1 ## 删除指定 key 的值 del k1
注意:
(error) NOAUTH Authentication required. 和 (error) NOAUTH Authentication required. 错误是因为没有输入密码
进入客户端输入 auth 密码
然后就可以操作了
添加开机启动服务
vi /etc/systemd/system/redis.service ## 添加以下内容 [Unit] Description=redis-server After=network.target [Service] Type=forking ExecStart=/opt/home/redis/bin/redis-server /opt/home/redis/bin/redis.conf PrivateTmp=true [Install] WantedBy=multi-user.target ## 重新加载配置文件 systemctl daemon-reload ### 服务操作命令 ### ### 必须用下列命令启动才可以用下列命令关闭和查看状态 ### ## 启动redis systemctl start redis.service ## 停止redis服务 systemctl stop redis.service ## 重新启动服务 systemctl restart redis.service ## 查看服务当前状态 systemctl status redis.service ## 设置开机自启动 systemctl enable redis.service ## 停止开机自启动 systemctl disable redis.service
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台reids都是主服务器,我们一般只配置从机就好了
搭建的主从集群结构
共包含三个节点,一个主节点,两个从节点。
使用三台虚拟机分别部署redis,模拟主从集群,信息如下:
IP | PORT | 角色 |
---|---|---|
192.168.0.3 | 6379 | master |
192.168.0.4 | 6379 | slave |
192.168.0.5 | 6379 | slave |
使用单面部署的方式按照上面的方法分别部署三台服务器
现在三个实例还没有任何关系,要配置主从可以使用replicaof 或者slaveof(5.0以前)命令。
有临时和永久两种模式
修改配置文件(永久生效)
在redis.conf中添加一行配置:slaveof <masterip> <masterport>
使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):
slaveof <masterip> <masterport>
注意:在5.0以后新增命令replicaof,与salveof效果一致。
这里我们为了演示方便,使用方式二。
通过redis-cli命令连接192.168.0.4,执行
./redis-cli -a java521 -p 6379
# 执行slaveof 或者 replicaof
slaveof 192.168.0.3 6379
replicaof 192.168.0.3 6379
通过redis-cli命令连接192.168.0.5,执行
./redis-cli -a java521 -p 6379
# 执行slaveof 或者 replicaof
slaveof 192.168.0.3 6379
replicaof 192.168.0.3 6379
通过redis-cli命令连接192.168.0.3,查看集群状态
./redis-cli -a java521 -p 6379 # 查看状态 info replication ## 发现connected_slaves:0 这是困为主节点设置了密码 # 修改两台从服务器的redis配置文件redis.conf vi redis.conf # 取消注释 masterauth <master-password> # 应更改为 masterauth java521 # 重新启动服务 systemctl restart redis.service ## 因为这里用的是临时模式 所以192.168.0.4、192.168.0.5还要重新发送 执行slaveof 或者 replicaof ## 192.168.0.3查看状态 info replication ## 让当前redis服务停止接收其他redis服务的同步,同时把自己升格为主数据库。 slaveof no one
执行下列操作以测试:
set a b
,再执行get a
get a
,再执行set a bb
get a
,再执行set a bb
可以发现,只有在192.168.0.3这个master节点上可以执行写操作,192.168.0.4和192.168.0.5这两个slave节点只能执行读操作。
主从切换的技术方法是:
当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费时费力,还会造成一段时间内服务不可用,这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
哨兵模式是一种特殊的模式,首先reids提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行,其原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。
如果主机宕机后恢复,只能归并到新主机下,当做从机,这就是哨兵模式的规则。
优点
缺点
这里我们搭建一个三节点形成的Sentinel集群,来监管之前的Redis主从集群。
三个sentinel实例信息如下:
节点 | IP | PORT |
---|---|---|
s1 | 192.168.0.3 | 27001 |
s2 | 192.168.0.4 | 27001 |
s3 | 192.168.0.5 | 27001 |
创建sentinel.conf
文件,添加下面的内容:
cp /opt/home/redis-6.2.6/sentinel.conf /opt/home/redis/bin/ cd /opt/home/redis/bin/ vi sentinel.conf # 15行 允许所有IP访问 bind 0.0.0.0 # 17行 去掉注释 protected-mode no ## 21行 sentinel监听端口,默认是26379,可以修改 port 26379 # 26行 改为后台运行 daemonize yes # 36行 logfile ""应改为 logfile "/opt/home/redis/bin/sentinel.log" ## 58行 当提供announce-ip时,Sentinel将在通信中声明指定的IP地址,而不是像通常那样自动检测本地地址。 sentinel announce-ip 192.168.0.3 ## 65行 指定工作目录 dir "/opt/home/redis/bin" ## 84行 sentinel monitor mymaster 127.0.0.1 6379 2 应改为 sentinel monitor mymaster 192.168.0.3 6379 2 # mymaster 主节点名称 自定义 # 192.168.0.3 6379 主节点的ip和端口 # 2 选举master时的quorum值 ## 86行 如果redis配置了密码,那这里必须配置认证,master和slave的密码应该设置相同 sentinel auth-pass mymaster java521 ## 117行 主节点或副本在指定时间内没有回复PING,便认为该节点为主观下线 S_DOWN 状态,默认是30秒 sentinel down-after-milliseconds mymaster 5000 ## 225行 指定故障转移超时(毫秒) sentinel failover-timeout mymaster 60000
192.168.0.4 和192.168.0.5进行同样的操作
分别启动3个redis实例,启动命令:
./redis-sentinel ./sentinel.conf
./redis-server ./sentinel.conf --sentinel
netstat -lnp | grep 26379
rm -rf sentinel.log
尝试让master节点192.168.0.3宕机,查看sentinel日志:
tail -f sentinel.log
问题:192.168.0.3重新启动之后,该节点不能跟选举后的master数据主从同步
## 查询信息
info replication
查看发现主链接状态为关闭
其余slave节点主链接状态为开启
查看mysql的日志发现,一直报身份验证
经过排查,原因是主机配置了redis密码,需要在从机redis.conf
中添加如下配置,修改从机的配置文件后,重启从机的redis服务,重新及进行连接
## redis.conf中添加
masterauth java521
再次查看,主从配置成功
在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。
1、新建SpringBoot项目
2、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3、在配置文件application.yml中指定sentinel相关信息
server:
port: 9527
spring:
redis:
# redis密码 必须一致
password: java521
sentinel:
# 指定master名称
master: mymaster
# 指定redis-sentinel集群信息
nodes: 192.168.0.3:26379, 192.168.0.4:26379, 192.168.0.5:26379
4、配置主从读写分离
@Bean
public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
return new LettuceClientConfigurationBuilderCustomizer() {
@Override
public void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder clientConfigurationBuilder) {
clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
};
}
这里的ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择:
5、编写接口
@RestController public class HelloController { @Autowired private StringRedisTemplate redisTemplate; @GetMapping("/get/{key}") public String getValue(@PathVariable String key) { return redisTemplate.opsForValue().get(key); } @GetMapping("/set/{key}/{value}") public String setValue(@PathVariable String key, @PathVariable String value) { redisTemplate.opsForValue().set(key, value); return "success"; } }
6、启动项目测试
这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:
分片集群需要的节点数量较多,这里我们搭建一个较小的分片集群,包含三个master节点,每个master包含两个slave节点
IP | 端口 | 角色 |
---|---|---|
192.168.0.3 | 6379 | master |
192.168.0.4 | 6379 | master |
192.168.0.5 | 6379 | master |
192.168.0.3 | 6380 | slave |
192.168.0.4 | 6380 | slave |
192.168.0.5 | 6380 | slave |
192.168.0.3 | 6381 | slave |
192.168.0.4 | 6381 | slave |
192.168.0.5 | 6381 | slave |
暂停启动的reids 和 sentinel
## 进入/opt/home/目录 cd /opt/home/ ## 将redis复制到880、8002、8003 cp -r redis 8001/ cp -r redis 8002/ cp -r redis 8003/ rm -rf /opt/home/8001/bin/redis.conf rm -rf /opt/home/8002/bin/redis.conf rm -rf /opt/home/8003/bin/redis.conf ## 分别更改端口为8001 8002 8003 vi 8001/bin/redis.conf ## 新增 8001 # 端口 port 8001 # 开启集群功能 cluster-enabled yes # 集群的配置文件名称,不需要我们创建,由redis自己维护 cluster-config-file nodes.conf # 节点心跳失败的超时时间 cluster-node-timeout 5000 # 持久化文件存放目录 dir "/opt/home/8001" # 绑定地址 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 192.168.0.3 # 保护模式 protected-mode no # 数据库数量 databases 1 # 日志 logfile "/opt/home/8001/run.log" # 密码 requirepass "java521" masterauth "java521" vi 8002/bin/redis.conf ## 新增 8002 # 端口 port 8002 # 开启集群功能 cluster-enabled yes # 集群的配置文件名称,不需要我们创建,由redis自己维护 cluster-config-file nodes.conf # 节点心跳失败的超时时间 cluster-node-timeout 5000 # 持久化文件存放目录 dir "/opt/home/8002" # 绑定地址 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 192.168.0.3 # 保护模式 protected-mode no # 数据库数量 databases 1 # 日志 logfile "/opt/home/8002/run.log" # 密码 requirepass "java521" masterauth "java521" vi 8003/bin/redis.conf ## 新增 8003 # 端口 port 8003 # 开启集群功能 cluster-enabled yes # 集群的配置文件名称,不需要我们创建,由redis自己维护 cluster-config-file nodes.conf # 节点心跳失败的超时时间 cluster-node-timeout 5000 # 持久化文件存放目录 dir "/opt/home/8003" # 绑定地址 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 192.168.0.3 # 保护模式 protected-mode no # 数据库数量 databases 1 # 日志 logfile "/opt/home/8003/run.log" # 密码 requirepass "java521" masterauth "java521"
8001/bin/redis-server 8001/bin/redis.conf
8002/bin/redis-server 8002/bin/redis.conf
8003/bin/redis-server 8003/bin/redis.conf
## 查看是否启动
netstat -lnp | grep 8001
netstat -lnp | grep 8002
netstat -lnp | grep 8003
虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。
我们需要执行命令来创建集群,在Redis5.0之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli中。
1)Redis5.0之前
Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。因为redis-trib.rb是有ruby语言编写的所以需要安装ruby环境。
# 安装依赖
yum -y install zlib ruby rubygems
gem install redis
然后通过命令来管理集群:
# 进入redis的src目录
cd /tmp/redis-6.2.4/src
# 创建集群
./redis-trib.rb create --replicas 1 192.168.0.3:8001 192.168.0.4:8001 192.168.0.5:8001 192.168.0.3:8002 192.168.0.4:8002 192.168.0.5:8003 192.168.0.3:8003 192.168.0.4:8003 192.168.0.5:8003
2)Redis5.0以后
我们使用的是Redis6.2.6版本,集群管理以及集成到了redis-cli中,格式如下:
cd /opt/home/8001/bin/
./redis-cli -a java521 --cluster create --cluster-replicas 1 192.168.0.3:8001 192.168.0.4:8001 192.168.0.5:8001 192.168.0.3:8002 192.168.0.4:8002 192.168.0.5:8003 192.168.0.3:8003 192.168.0.4:8003 192.168.0.5:8003
命令说明:
redis-cli --cluster
或者./redis-trib.rb
:代表集群操作命令create
:代表是创建集群--replicas 1
或者--cluster-replicas 1
:指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1)
得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master输入"yes"
通过命令可以查看集群状态:
./redis-cli -a java521 -p 8001 cluster nodes
尝试连接8001节点,存储一个数据:
## 连接 ./redis-cli -p 8001 -a java521 ## 存储数据 set num 123 ## 读取数据 get num ## 再次存储 set a 1 ## 报错了 # 127.0.0.1:8001> set a 1 # (error) MOVED 15495 192.168.0.3:8002 # 127.0.0.1:8001> get a # (error) MOVED 15495 192.168.0.3:8002
集群操作时,需要给redis-cli
加上-c
参数才可以:
./redis-cli -c -p 8001 -a java521
## 这次可以了
127.0.0.1:8001> set a 1
-> Redirected to slot [15495] located at 192.168.0.3:8002
OK
192.168.0.3:8002> get a
"1"
192.168.0.3:8002> set b 123
-> Redirected to slot [3300] located at 192.168.0.3:8001
OK
192.168.0.3:8001> get b
"123"
完成!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。