Redis_2 持久化
1. Redis.conf详解
redis.conf从上向下详解
1.1 单位配置
1 redis对单位的大小写是不敏感的, 单位可以是gb, GB, Gb等等。
2 可以包含其他配置文件的配置
1.2 网络配置
绑定的ip和端口号
bind127.0.0.1
protected-mode yes#保护模式
port 6379
1.3 通用配置
General
1 守护进程开启(后台运行)
daemonize yes #守护进程开(如果使用docker, 这个需要为no)
supervised no #不重要
pidfile /var/run/redis_6379.pid #如果以后台方式运行,需要制定一个pid文件
loglevel notice #日志级别, 可以在注释里找可以修改的级别
logfile"" #日志的文件位置名
databases16 #数据库的数量,默认是16个数据库
always-show-1 ogo yes #是否总是显示启动logo
1.4 快照配置
主要和持久化有关系
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb.aof
redis是内存数据库,如果没有持久化,那么数据断电及失!
#如果900s内,如果至少有一个1个key进行了修改,就进行持久化操作
save 900 1
#如果300s内,如果至少10key进行了修改,就进行持久化操作
save 300 10
#如果60s内,如果至少10000key进行了修改,就进行持久化操作
save 60 10000
stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要继续工作
rdbcompression yes #是否压缩rdb文件,需要消耗一些cpu资源
rdbchecksum yes #保存rdb文件的时候,进行错误的检查校验
dir./ #rdb文件保存的目录
1.5 复制配置
replication复制, 和主从复制有关(暂时跳过)
1.6 安全配置
security, 和密码有关
requirepass xxxx #这个用来设置密码(在配置文件中设置的)
而如果在redis-cli之后, 想要设置密码可以这样:
config set requirepass "password"
#这时候要ping的时候也提示NOAUTH
auth “password” #这样可以认证
1.7 客户端的限制配置(一般不用管)
client的设置(比如最大客户端的设置)
maxclients 10000 #设置能连接上redis的最大客户端的数量
maxmemory<bytes:> #redis配置最大的内存容量
maxmemory-policy noeviction #内存到达上限之后的处理策略
1、vo1ati1e-1ru:只对设置了过期时间的key进行LRU(默认值)
2、a11keys-1ru:删除1ru算法的key
3、volati1e-random:随机删除即将过期key
4、a11keys-random:随机删除
5、vo1ati1e-tt1:删除即将过期的
6、noeviction:永不过期,返回错误
1.8 APPEND ONLY的配置
APPEND ONLY模式 aof的配置
appendonly no #默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分所有的情况下,rdb完全够用!
appendfilename"appendon1y.aof" #持久化的文件的名字
#appendfsync always #每次修改都会sync。消耗性能
appendfsync everysec #每秒执行一次sync,可能会丢失这1s的数据!
#appendfsync no #不执行syc,这个时候操作系统自己同步数据,速度最快!
2. Redis持久化
redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,一旦服务器进程退出,服务器中的数据库状态也会消失。所以redis提供了持久化功能
2.1 RDB持久化(Redis Database)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。
Rdis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。默认使用的就是RDB,一般情况下不需要修改这个配置。
rdb方式保存的是dump.rdb文件(都是在配置文件中进行配置的)
触发redis进行rdb持久化的操作:
1、save的规则满足的情况下,会自动触发rdb规则(save命令的执行)
2、执行flushall命令,也会触发我们的rdb规则(flashall命令的执行)
3、退出redis,也会产生rdb文件(shutdown时)
4、符合config的设置(save 60 5 etc.)
备份就自动生成一个dump.rdb
恢复rdb文件:
把rdb文件放在redis的启动目录下即可(config get dir获取文件需要在的目录), redis会自动检查dump.rdb文件
优点:
1、适合大规模的数据恢复
2、对数据的完整性要不高
缺点:
1、需要一定的时间间隔进程操作,如果redis意外宕机了,这个最后一次修改数据就没有的了
2、fork进程的时候,会占用一定的内容空间(fork比较耗资源)
2.2 AOF(Apend Only File)
将所有命令都记录下来, 和history一样, 恢复的时候把这个文件全部执行一遍
父进程fork一个子进程出来, 然后这个子进程进行操作;
以日志的形式来记录每个写操作,将Redis:执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,rdis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
AOF保存的是appendonly.aof文件, 需要在上面的1.8配置中去开启aof配置。
aof和rdb同事开启都会进行备份。恢复时优先加载aof,找不到aof文件再去加载rdb
-
如果自己手动修改了aof文件,当redis重启后重回拒绝连接, 这时可以用redis文件目录中提供的工具redis-check-aof来自动修改aof数据
而这个工具实际上是截断错误的语句, 只执行前面正确的语句, 所以在高版本的redis中都没有这个工具了
优点:
1、每一次修改都同步,文件的完整会更加好!
2、每秒同步一次,可能会丢失一秒的数据
3、从不同步,效率最高的!
缺点:
1、相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢!
2、Aof运行效率也要比db慢,所以我们redis默认的配置就是rdb持久化!
如果在项目中, 只把redis作为缓存的话, 是不需要持久化的。
3. Redis发布订阅
三个角色:
发布者, 频道, 订阅者;
而频道就是一个队列, 里面是一个订阅者的队列。
使用: 两个terminal, 一个是发布者, 一个是订阅者
订阅者:
SUBSCRIBE someChannel
发布者:
PUBLISH someChannel "Redis PUBLISH test"
4. Redis主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis.服务器。前者称为主节点(master八eader),后者称为从节点
(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主。
我们在配置主机和从机的时候, 只需要配置从机, 因为redis默认自己为主机。
redis-cli连接redis-server之后, 使用info repliction
来查看当前库的信息
角色默认master
4.1 redis集群配置
需要启动3个redis, 作为集群, 一主二从
首先复制redis.conf2份,
conf中需要修改的配置
# 端口号
# pidfile的文件名(进程的文件名)
# pid(port ID):记录了进程的 ID,文件带有锁。可以防止程序的多次启动。
# logfile 日志文件名
# dump.rdb文件名称
需要一个主机, 两个从机, 需要在两个从机上去认谁是主机
在从机中输入命令:
SLAVEOF host port #就可以, 然后info replication可以返回:
这时, 角色已经变成从机
如果主机中设置了密码, 需要在从机的配置文件中设置masterAuth
上述方法是在命令行中进行设置的,只是暂时的, 如果要持久化的进行配置, 则需要在config中配置
主从定好之后, 只有在主机中可以写入, 从机只能读取;当然, 现在配置后, 在主机set的k1, 在从机中get k1是可以获取到值的。但在从机中set k2是不被允许的。
当有一个节点宕机后:
主机宕机: 从机只能读, 不能写入;当主机重新连接后, 恢复正常;
从机宕机: 主机写入的数据, 在从机恢复后依然可以在从机上get到;
4.2 复制原理
Slave启动成功连接到master后会发送一个sync命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制:而slve服务在接收到数据库文件数据后,将其存盘并加载到内存中。(每次重连后都会进行)
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步(主机set进去之后, 会增量复制到从机)
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
其他连接方式: M-s1(as M to s2) - S2, 这时, s1的role依然是slave, 只能读, 不能写。
如果没有哨兵模式, 即无法自己选举主节点, 当master宕机了, 需要在从机的命令中输入SlaveOf No One
, 但是当master回来之后, 依然当不了主机了。
4.3 哨兵模式
自动当能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先Rdis提供了哨兵的命令,哨兵是一个独立的进程作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
有点类似于zookeeper和dubbo的心跳检查, 但这里是哨兵发送请求给每个节点, 通过回应判断是否存活。如果害怕一个哨兵进程出问题, 可以配置多个哨兵。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failoveri(故障转移)过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
哨兵进程在文件夹中:
启动哨兵前, 需要写一个配置文件, 文件名固定为sentinel.conf
sentinel monitor 自定义哨兵名称 host port 1 # 哨兵监视哪个节点, 这个1是 一个哨兵检测主redis服务异常了就判断主redis挂了
启动:
redis-sentinel ./sentinel.conf
之后, 当master shutdown, 会自动swith-master, 从两个从机中选一个作为master。
当master重新回来后, 也只能作为新master的slave存在。
5. redis缓存穿透,击穿和雪崩
5.1 缓存穿透(查不到导致)
缓存穿透的概念很简单,用户想要查询一个数据,发现rdis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方法: 给redis中插入一个值为空的缓存, 或者在查询前过滤这个请求。
- 布隆过滤器:
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力;
- 缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保特一致性的业务会有影响。
5.2 缓存击穿(某个key失效后量太大)
这里需要注意和缓存击穿的区别,缓存击穿,是指一个ky非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案:
-
设置热点key不过期
-
使用分布式锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
5.3 缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。Redis宕机。
如缓存在某个时间点集体过期, 然后有大量的请求直接去查询数据库。
解决方案:
-
redisi高可用
这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。(异地多活!) -
限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个ky只允许一个线程查询数据和写缓存,其他线程等待。 -
数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的ky,设置不同的过期时间,让缓存失效的时间点尽量均匀。1