后端开发之Redis篇----持久化与主从同步及缓存过期处理

Redis进阶

持久化 Persistence

Redis提供了两种不同的持久化方式,具体可以分为:使用快照的rdb式的全量持久化和监控写入操作的AOF式的追加式的增量持久化

RDB

RDB全称Redis DataBase 其实现原理为每个一段时间把内存中的数据写入磁盘的临时文件,作为快照,恢复的时候把快照文件读进内存。如果宕机重启,那么内存理的数据肯定会没有,那么再次启动redis后,就能恢复了。

  • 优点
    1.每个一段时间进行备份,全量备份,这样更具服务器的实际运行情况来自定以间隔时间
    2.冗灾方式比较简单,备份下来的dump.rdb文件还能直接上传到数据中心进行备份,例如可以将文件直接上传的hdfs/s3文件系统上进行保存,如果是对每一次的rdb文件都进行备份的话,还能进行专门的版本管理
    3.redis进行rdb备份时是使用子进程来操作的,主进程是不会有任何的io操作,保证了数据的完整性
    4.相对AOF模式来说,这种方式更方便对巨量数据的快速重启恢复

  • 缺点
    1.由于自定义了间隔时间来备份,如果间隔时间过长的话,系统在间隔时间中间端发生了宕机情况,那么只能恢复到最近的一个备份点上,这样最近的备份点到宕机的这段时间里的数据将无法保存下来,这样就造成了数据的丢失。
    2.子进程所占用的内存比和主进程是一模一样的,且当数据量巨大时,将造成CPU的严重负担

上一篇博文中,我们在redis.conf中配置了一个这样的属性参数
dir ./ 改成了 dir /usr/local/redis/working
我们的dump.rdb文件就是存储在这个路径上的

使用RDB持久化的时候,可以在redis.conf上添加的配置有:

save 900 1 # 如果一个key更新则15分钟后备份
save 300 10 # 如果10个key更新,则5分钟后备份
save 60 10000 # 如果10000个可以更新,则1分钟后备份
save 10 3 # 这个是我自己加的,10个key更新了,3分钟后备份,大家可以根据自己公司数据的并发量来决定

stop-writes-on-bgsave-error yes # 默认情况为yes,当save过程出错,则停止写操作,如果是no可能会造成数据不一致,所以推荐使用yes

rdbcompressin yes # 是否对rdb文件进行压缩,no的话可以节省cpu损耗,但文件会很大,如果是定期备份并上传数据中心的话,推荐使用压缩

rdbchecksum yes # 使用CRC64算法检验对rdb进行数据校验,有10%的性能损耗

总结:RDB对大量数据的恢复比较友好,但是数据的完整性和一致性可能会不足

AOF

AOF的模式是把每一次的写入操作都记录下来,类似于一个日志文件。文件以追加的模式添加数据而不是直接修改或者覆盖。redis的aof恢复其实就是把追加的文件从开始到结尾读取并按照这样再操作一遍。

  • 优点
    1.AOF更加耐用,可以以秒级别为单位进行备份,也可以实时对每一条数据进行备份,其完整性更高
    2.以log日志形式追加,如果磁盘满了,会执行redis-check-aof工具
    3.当数据太大的时候,redis可以在后台自动重写aof。当redis继续把日志追加到老的文件中去时,充血也是非常安全的,不会影响客户端的读写操作
    4.AOF日志包含了所有写操作,会更加便于redis的解析恢复

  • 缺点
    1.相同的数据,同一份数据,AOF会大于等于RDB
    2.针对不同的同步机制,AOF会比RDB满,因为AOF对每次备份操作会比较频繁,这样将影响到redis的性能

    使用AOF持久化的时候,同样可以在redis.conf下添加如下配置:

appendonly no # 默认关闭,yes为开启aof持久化

appendfilename "apendonlu.aof" # aof的文件名

# appendfsync no 不同步
# appendfsync always 每次写如操作对分备份,完全并数据完整,但损耗性能
appendfsync everysec # 每秒同步一次

# 重写的时候是否要同步,no可以保证数据安全
no-appendfsync-no-rewrite no

# 重写机制:避免文件越来越大,自动优化压缩指令,会fork一个新的进程去完成重写动作,新进程里的内存数据会被重写,此时旧的aof文件不会被读取使用,类似rdb
# 当前aof文件的大小是上次aof大小的100% 并且文件体积达到64m,满足两者则触发重写,可以自己修改
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

RDB和AOF间的选择

  1. 如果能接收一段时间内的数据丢失的话,优先选择RDB
  2. 如果对实时性有极大需求的话,选择AOF,并考虑同步的频率
  3. 存储空间能满足的话,可以考虑RDB和AOF一起做持久化,RDB作为冷备份,可以在不同时期对不同版本做恢复,AOF为热备份,保证数据仅仅只有1秒的损失。当AOF不可用的时候,使用RDB恢复。Redis先加载AOF,不行再使用RDB恢复

主从同步

1.架构
1 个 master(写) <----> N 个 slave(读)
以我司为例
一个master加两个slave。当然有些公司可以在一个slave下再接这个slave的子slave,而不是使用一个master接多个slave的方法,这样可以避免master和多个slave的网络io交互
master和slave之间会相互ping通来感知对方的存在

假设现在有3台机器:191,192和193
我们以191为master,另外两个为slave
可以使用命令:

info replication # 来查看主从节点的情况

要构建集群,需要对192和193两个节点的redis.conf进行修改

replicaof <masterip> <masterport> # 配置master节点地址
masterauth <master-password> # 当master有密码时,需要填入
replica-read-only yes # slave节点是只读的

当集群构建完成后,slave节点宕机后在恢复也是能同步在其宕机这段时间内,master新添加的数据的。如果master宕机了,在slave节点上使用命令info replication 可以看到master-status是down的

以上是通过磁盘进行的数据同步,这种方式,在master和slave节点初次构建同步时,是将master的rdb文件传输到slave节点上,然后slave再加载这个rdb文件的。当完成初始化后,就是每当master有新数据写入就会马上同步到slave上了,可以不再使用rdb文件传输了

当时,如果redis服务器上的磁盘是传统的机械磁盘,其吞吐量比较少的时候,可以考虑使用无磁盘化同步方案
master的内存数据是通过socket同步到slave内存中的,没有经过磁盘。
redis.conf配置:

repl-diskless-sync no # 默认关闭,yes为开启无磁盘话同步
repl-diskless-sync-deley # 开同步前的时间等待

Redis缓存过期处理与内存淘汰机制

对已过期的key如何处理
redis有两种方式

  • 主动定时删除
    定时随机的坚持过期的key,如果过期则清理删除
    redis.conf配置
dynamic-hz yes # 开启主动删除机制
hz 10 # 定义每隔多少秒进行一次随机抽查
  • 被动惰性删除
    当客户端请求到一个已经过期的key的时候,那么redis会检查这个key是否过期了,如果过期了,则删除,然后返回一个nil。这种策略对cpu比较友好,不会有太多的损耗,但内存占用会比较高

内存管理memory-manager
当内存到达阈值的时候,redis会清理那些永远不会过期(就是没有超时设定)的key
在redis.conf中有这样的参数来定义最大内存阀值

maxmemory <bytes> # 以字节为单位定义内存量

# 内存管理策略
maxmemory-policy noeviction
# noeviction 旧缓存永不过期,新缓存设置不了,返回错误
# allkeys-lru 清除最少用的旧缓存,然后保存新的缓存(推荐使用)
# allkeys-random 在所有的缓存中随机删除(不推荐)
# volatile-lru 在那些设置了expire过期时间的缓存中,清除最少用的旧缓存,然后保存新的缓存
# volatile-random 在那些设置了expire过期时间的缓存中,随机删除缓存
# volatile-ttl 在那些设置了expire过期时间的缓存中,删除即将过期的

# 下面是redis.conf的原注解
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
发布了118 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_39702831/article/details/104749825