一、Redis面试要点记录
1.什么是rdb?
rdb 称之为redis 的持久化方案之一,当满足3个默认条件时,会生成一个dump.rdb(以二进制的方式进行存储的),当需要恢复数据时,就去加载dump.rdb,进行数据的回复
2.三个条件
1 10000 // 1秒10000次存储
300 10 // 300秒10次存储
900 1 // 900秒1次存储
3.redis持久化指令
- save :阻塞
- bgsave : 异步
- 也会阻塞一会:fork进程 出来的这个过程会出现短暂的阻塞
4.rdb的原理
当调用bgsave后,会fork( redis-rdb-bgsave )出来一条子进程,这条子进程和主进程一模一样,子进程会去进行持久化,在此过程中,主进程不进行任何的持久化操作,这就保证了主进程的高效,还会生成一个temp.rdb,在持久化完毕后,会去利用dump.rdb 去整合temp.rdb
二、Redis持久化服务
1.aof
以日志的方式来记录用户的 写操作,当需要恢复数据时,就去拿到aof文件重新的再去执行一遍指令,aof 默认是关闭的
2.aof的同步策略
aof : 推荐使用: ervery sec
指令 | 含义 |
---|---|
ervery sec | 每秒记录 |
always | 每次都进行记录 |
no | 把记录的权利交给当前操作系统,这种方式 效率最高,但是最不稳定 |
3.aof的重写
主动重写bgrewriteof
被动重写
-
aof文件必须大于64mb
-
aof文件必须是原来一倍
-
就是去简化咱们的aof文件,把很多指令进行组合,缩写
最后总结:实际开发中使用的方式 通常而言都是 rdb +aof 用rdb 来恢复大量的数据 用aof 来恢复少量数据,用aof来防止rdb 丢失的时间段数据 如果数据量大的话-> rdb 快 如果数据量小的话-> aof 快
-
三、Redis事务
- 事务
- 事务就是一系列操作的整体,要么都成功,要么都失败(acid,隔离级别 )
- redis 是弱事务
- 有的可以成功,有的可以失败,可以一次执行多个命令。本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞
set k1 v1
set k2 v2
set k3 v3
事务队列 ->序列化
case1 正常执行
case2 放弃事物
case3 全体连坐 : 语法错误,所有错误
case4 冤头债主 : 逻辑错误,单独找那一个
multi 打开事务
exec :提交事务
discard :放弃事务
multi
set k1 哪怕你的语法有问题,他也不会告诉你说语法有问题
(ok)
set k2 v2
(ok)
exec
multi
set k1 v1 哪怕你的语法有问题,他也不会告诉你说语法有问题
(ok)
incr k1
(ok)
set k2 v2
(ok)
set k3 123
exec
注意:如果是逻辑错误,此时就不会执行错误的那句话,但是其他的会执行
- exec 开始执行了
- discard :放弃事务的执行
redis 还支持乐观锁操作
线程A
set banlance 1000
watch banlance
muilt
set banlance 1
exec
线程B
watch banlance
muilt
set banlance 10
exec
可以
四、redis 的过期策略和淘汰机制
过期策略
set k1 v1 10秒
内存 :硬盘上的程序在运行过程中放到的空间
cpu :处理核心
按照我们的想法,如果数据过期了,我们就应该删掉,但是这样做的话,其实会比较消耗cpu的性能,计算机就会对每一个需要过期的key 监视着他,增加了cpu的工作量 ,我们不能让他去时实际控 ->我们就希望找到一个既能让cpu舒服,又能清理掉内存的手段 ,
定时策略
惰性策略
redis 采用了这种方案:当我们去获得一个对应的key时,他会先去执行EXPIRREIFNEED() -> 判断当前这个key 是否已经过期,如果过期了的话,会删除,再给你返回一个空
面试题
为什么我明明把key都设置了过期,但是我的内存占用率还是那么高?
定期策略(简单) --> 讲解简单版的理解 ->完全可以支持你找到10k左右的工作
最简单版:我们的redis 会去定期的检查我们的数据,看是否过期,如果说过期的话,我们就会删除掉他
中间版:在redis 中 hz 的配置默认是10,每次执行时间是 250ms/10 ,他会去每一个库进行随机的筛选,如果发现选出来的key中有超过1/4 的key 是过期key,此时会去再操作一次当前这个库,如果没有超过1/4 则进行下一个库的筛选,但是如果我说操作某一个库的时间超过了250ms/10 ,此时无论是有没有筛选出来对应的过期key,那么都要进行下一个库
redis 采用的方案
定期删除 + 惰性删除
淘汰机制
淘汰机制指:如果咱们的redis 最大 maxmemory,我们的redis 会怎么处理他呢 —>淘汰
-
移除最近最少使用的key,默认设置了过期的
-
移除最近最少使用的key -》 没有设置过期的
-
随机移除,默认设置了过期的
-
随机移除
-
移除在规定时间内,更早的过期的key 9 月28 号 ->淘汰机制
五、redis主从复制
1. 为啥要用主从复制 ?
目的:是为了实现高可用-> 99.99% 都可以使用
2. 主从
master:负责读和写都ok
salve :只能进行读,同时salve 可以进行投票选举出来master
3. 具体步骤(适合记忆版)
-
数据同步:
- 1.全量更新 :把所有的数据都进行一次复制 rdb
- 2.增量更新 :把部分增加的数据再次进行复制 aof
-
3.1 连接
1.配置从机(配从不配主) salveof ip port
2.salve 就会保存master信息 ,master 也会记录salve 的信息
3.salve 去建立socket 连接
4.salve 定期给master 输送心跳 ping pong -
3.2 数据同步
-
salve 在连接完成后,会发送一个同步请求
-
master 在收到同步请求后,会去执行bgsave 的指令进行持久化->生成一个最新的dump.rdb
-
master 创建一个增量缓存区
-
如果再没有完成全量更新前来写请求,我们的master 就会将操作的指令存储到缓存区中
【set k1 v1 set k1 v2 set k1 v3 set k1 v4】
-
master 就会将dump.rdb 文件发送到slave端
-
salve 如果收到这个请求后,salve 就会数据的同步,全量更新
-
当我们的salve 进行完全量更新后,我们的salve 就会再次告诉咱们的master 说我已经全量更新完毕了,请给我增量数据
-
master 将缓存区中的数据发给salve ,先去进行一次重写之后 (aof文件的瘦身),aof 文件交给salve ,salve 会进行增量更新
-
-
注意的细节:
- 咱们的数据同步应该尽量的错峰
- 我们应该注入缓存区大小的设置 ,因为如果缓存区数据量过小的话,就可能产生数据丢失的
- 主从复制 = rdb+aof
4. 面试版
- 主从建立连接
- salve 在连接完成后,会发送一个同步请求
- master 会对salve 进行全量更新
- 如果此时再来数据,会存储到缓冲区中,然后再让缓存区中的数据对salve 进行增量更新
5. redis 主从的配置(95 以上都是运维来操作)
1、直接手动输入命令 slaveof ip port
2、在启动时 + 参数
3、在配置文件中进行配置
4、断开连接 salveof no one
小细节:当我们在连接master 时,master 会自动进行数据同步
6. 主从中的名词介绍
runid : 服务器id ,表明当前这台服务器是谁,每次server 启动时,这个runid 都会变
增量缓存区
- 队列
- offset 偏移量
当我们在进行数据增量同步时,我们的redis 将新来的数据写入到 复制缓存区中去
-
由于有多个salve ,但是master 只有一个,每个slave 同步数据的效率又是不一样的,所以master 记录下来各个不同的salve 节点接收到的缓存区数据到底哪儿了(offset) ,salve 也得去接受缓存区数据到底哪儿了(offset),之所以两个人都记,实际上为了以后去进行对比,来确保这个数据到底是丢了呢? 还是没丢呢?
情况一、缓存区队列满了
情况二、网络波动有可能导致丢数据
六、zookeeper的主从
1. zookeeper角色
leader
follower
2. zookeeper数据同步 2pc 提交
zookeeper leader 收到请求后,先将数据写入一份到leader 日志文件中,leader 就会发起一次 提议, follower 收到提议后,他会将数据也写入到自己的日志文件中,如果写入成功,叫表明他有能力将数据拿到自己的节点上,回复leader 一个ack ,如果leader 收到超过半数的ack ,此时zookeeper 就会进行同步,先将自己的数据写入到自己的节点中,然后再提交给follower 一个commit,从节点再去进行数据写入