redis 数据持久化,主从,哨兵等
一:redis的持久化
1. rdb(快照):简单的说就是将redis内存中的所有数据都保持的磁盘中,生成dump.rdb文件
保存策略:save xx kk 意思是在xx秒内,变化的key数量到达kk时就会生成一次dump.rdb文件,默认的策略有:
save 900 1
save 300 10
save 60 10000
如果要关闭rdb,只要注释调所有的策略即可,我们也可以通过在命令行中执行save或者bgsave命令即可生成对应的dump.rdb文件,区别在于bgsave是异步执行的,不会阻塞客户端的连接,上面配置的策略也是bgsave方式执行的
优点:rdb的优点在于:数据量小,重启后,数据恢复非常快
缺点:rdb的缺点也很明显:生成rdb文件需要比较长的时间,如果在生成rdb文件的后,系统刚好挂了,会丢失一部分数据
2. aof: 该模式的作用是将我们执行的增删改命令保存到appendonly.aof
默认是不开启,需要配置开启:appendonly yes 在命令行中,可以执行bgrewriteaof生成aof文件
保存策略:(生产建议:everysec)
appendfsync always 来一条命令就追加一次到aof中
appendfsync everysec 每一秒追加一次命令到aof中
appendfsync no 由操作系统决定啥时候追加命令到aof中
优点:aof:数据安全,最多丢失1秒的数据
缺点:文件会比较大,数据恢复需要的时间比较长
aof重写:aof中可能存在大量没用的命令,如,我们连续执行10次incr a ,让a的值递增到10,这10条命令等价于set a 10,所以aof重写可以减少aof文件的大小,重写是redis fork出一个子线程去做的,不会阻塞客户端命令的处理
重写的时机:可以在命令行执行bgrewriteaof命令,或者配置如下策略:
auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就 很快,重写的意义不大
auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写
3.混合持久化:在aof的基础上结合rdb模式,在aof重写时,不再是将命令写到aof中,而是将数据持久化到aof中,后续客户端的命令,在追加到aof中
开启:必须开启aof持久化:appendonly yes
aof‐use‐rdb‐preamble yes
二:redis主从架构
主从的配置:redis.conf
1 2 3 4 5 6 7 8 9 10 | port 6380 修改端口 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" dir /usr/local/redis‐5.0.3/data/6380 # 指定数据存放目录 # 需要注释掉bind # bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通 过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可) 这里并不是指客户端的ip地址 replicaof 192.168.0.60 6379 # 配置主节点的 ip和端口 masterauth 123456 #主节点的密码 replica‐read‐only yes # 配置从节点只 |
启动从节点:redis‐server redis.conf
执行info 命令可以查询主从信息
主从复制的原理:
三. redis 的事务:redis的事务不支持回滚操作,redis的管道 Pipeline 可以一次发送多条命令到redis中,减少网络开销,但不会保证所有的指令都执行成功,但我们可以使用lua脚本来保证原子性从而实现事务
四. 哨兵模式
sentinel是特殊的redis服务,它不提供读写操作,它负责监控主从节点,client访问sentinel获得主节点的信息,后续client端就跟主节点交互即可,当主节点挂了,sentinel会选举出新的主节点,并通知client端,client端会订阅该消息
配置:
1 2 3 4 5 6 7 8 9 10 11 | 复制一份sentinel.conf文件 cp sentinel.conf sentinel‐26379.conf 将相关配置修改为如下值: port 26379 daemonize yes pidfile "/var/run/redis‐sentinel‐26379.pid" logfile "26379.log" dir "/usr/local/redis‐5.0.3/data" # sentinel monitor < master ‐redis‐name> < master ‐redis‐ip> < master ‐redis‐port> < quorum > # quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效 sentinel monitor mymaster 192.168.0.60 6379 2 # mymaster这个名字随便取,客户端访问时会用,后面的ip端口是主节点的ip和端口 < br >sentinel auth-pass mymaster 123456 # 主节点的密码< br >requirepass 123456 #该节点的密码 |
启动:src/redis‐sentinel sentinel‐26379.conf
五:docker 搭建哨兵集群实战:
1.主从的配置:配置三个节点 6379 6378 6377
以redis-6377.conf 为例子,其他的一样:
1.#bind 127.0.0.1 注释掉bind
2. 修改端口:port 6377
3. pidfile /var/run/redis_6377.pid
4. logfile "6377.log"
5. replicaof 192.168.56.11 6379 #主节点的IP和端口 主节点不用写
6. masterauth 123456 #连接主节点的密码,即使是主节点也要填密码,不然主节点挂了,重启变成了从节点,从主节点同步数据会失败
7. replica-announce-ip 192.168.56.11 #本节点对客户端的ip,填宿主机的,因为不填的化,默认是docker容器的ip,springboot访问不到
8. replica-announce-port 6377 #本节点对客户端的端口,填宿主机的
9. requirepass 123456 #登录密码
2. 哨兵的节点的配置:三个节点 26379 26378 26377
以sentine-26377.conf为例子:
1 2 3 4 5 6 7 8 | 1. pidfile /var/run/redis-sentinel-26377.pid 2. logfile "26377.log" 3. sentinel announce-ip 192.168.56.11 #宿主机的ip,不然springboot会连接失败 4. #requirepass 123456 千万别设置密码,不然springboot连接会有问题,主从节点有密码即可 5.sentinel monitor mymaster 192.168.56.11 6379 2 #主从系统主节点 的ip和端口 6. sentinel auth-pass mymaster 123456 #主节点的密码 7. port 26377 端口 8. daemonize no |
linux新建文件夹:
主从的命令:
#主从启动命令: docker run -v /redis/conf:/usr/local/etc/redis -d -v /redis/data/6379:/data -p 6379:6379 --name redis-6379 redis:6.0 redis-server /usr/local/etc/redis/redis-6379.conf docker run -v /redis/conf:/usr/local/etc/redis -d -v /redis/data/6378:/data -p 6378:6378 --name redis-6378 redis:6.0 redis-server /usr/local/etc/redis/redis-6378.conf docker run -v /redis/conf:/usr/local/etc/redis -d -v /redis/data/6377:/data -p 6377:6377 --name redis-6377 redis:6.0 redis-server /usr/local/etc/redis/redis-6377.conf
哨兵的启动:
# 启动sentinel集群 docker run -v /redis/sentinel/conf:/usr/local/etc/redis -d -v /redis/sentinel/data/26379:/data -p 26379:26379 --name redis-26379 redis:6.0 redis-sentinel /usr/local/etc/redis/sentine-26379.conf docker run -v /redis/sentinel/conf:/usr/local/etc/redis -d -v /redis/sentinel/data/26378:/data -p 26378:26378 --name redis-26378 redis:6.0 redis-sentinel /usr/local/etc/redis/sentine-26378.conf docker run -v /redis/sentinel/conf:/usr/local/etc/redis -d -v /redis/sentinel/data/26377:/data -p 26377:26377 --name redis-26377 redis:6.0 redis-sentinel /usr/local/etc/redis/sentine-26377.conf
启动后的效果:
整合springboot:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> <version>2.0.9.RELEASE</version> </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> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> </dependencies>
配置:
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = {DemoApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class DemoApplicationTests { @Autowired private StringRedisTemplate stringRedisTemplate; @Test public void doTest() { ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue(); int i=0; while (true){ try { stringStringValueOperations.set("a"+i,i+""); i++; TimeUnit.SECONDS.sleep(2); }catch (Exception e){ System.out.println("i:"+i+e.getMessage()); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程