Redis优化之持久化

发布于:2024-06-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.Redis高可用

在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。
但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服务(如主从分离、快速容灾技术),还需要考虑数据容量的扩展、数据安全不会丢失等。

在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和 Cluster集群,下面分别说明它们的作用,以及解决了什么样的问题。

  • 持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
  • 主从复制:主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
  • 哨兵:在主从复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
  • Cluster集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

2.Redis 持久化

持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。
 

Redis 提供两种方式进行持久化:

  • RDB 持久化:原理是将 Reids在内存中的数据库记录定时保存到磁盘上。
  • AOF 持久化(append only file):原理是将 Reids 的操作日志以追加的方式写入文件,类似于MySQL的binlog。

由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。

RDB 持久化                                                                                                                                      定时的将redis在内存中的数据进行快照并压缩保存到硬盘里

  • 手动触发:bgsave命令 
  • 自动触发:满足配置文件中 save n m 的规则(在n秒内发生了m次数据更新就会自动触发);主从复制在做全量复制时;执行shutdown命令关闭数据库时
  • 工作流程:redis父进程会fork子进程来进行RDB持久化快照保存内存数据到硬盘里,文件名:dump.rdb
  • 优缺点:RDB持久化保存的文件占用空间较小,网络传输快,恢复速度比AOF更快,性能影响比AOF更小; 实时性不如AOF,兼容性较差,持久化期间在fork子进程时会阻塞redis父进程

 AOF持久化                                                                                                                                       实时的以追加的方式将redis写操作的命令记录到aof文件中

  • 工作流程:命令追加(将写操作命令追到aof_buf缓冲区)
  • 文件写入和同步(文件名:appendonly.aof,同步策略:appendfsync everysec|always|no)文件重写(减少aof文件占用空间的大小和加快恢复速度,定期执行bgrewriteaof命令触发)
  • 优缺点:实时性比RDB更好,支持秒级持久化,兼容性较好;持久化保存的文件占用空间更大,恢复速度更慢,性能影响更大,AOF文件重写期间在fork子进程时也会阻塞redis父进程,且IO压力更大

RDB和AOF的区别可根据 工作方式、实时性、占用空间、恢复速度、兼容性、IO性能影响 这几方面进行描述。

3.Redis性能管理

内存碎片:
通过 info memory 命令查看内存的使用情况。

mem_fragmentation_ratio的值如果超过了1.5,建议可以考虑进行内存碎片的清理了。
mem_fragmentation_ratio的值如果小于1,说明物理内存不够真实数据的保存了,此时已经开始使用swap交换空间了,会导致redis性能的严重下降。应该考虑增加物理内存或减少redis内存占用。

config set activedefrag yes    #开启自动内存碎片清理
memory purge                   #手动内存碎片清理
注:由于内存碎片清理是redis主线程执行的,会发生阻塞。因此需要合理配置对应的参数和方式,保证redis的高性能。

4.Redis优化 

1)开启AOF持久化,设置AOF刷盘策略为everysec(每隔1秒执行一次刷盘操作),只在业务低峰期执行AOF文件重写,减少磁盘的开销
2)缩短键值对存储长度,避免存储bigkey导致操作耗时
3)给key设置合理的过期时间,尽量避免大量key集中过期
4)设置内存上限(maxmemory),并设置内存数据淘汰策略(maxmemory-policy),一般最常使用的是volatile-lru(只删除最近最少访问并设置了过期时间的键)或 allkeys-lru
5)开启自动内存碎片清理(activedefrag yes)
6)开启lazy-free机制(lazyfree-lazy-eviction yes、lazyfree-lazy-expire yes、lazyfree-lazy-server-del yes),将删除过期key的操作放到后台线程执行,以减少删除对Redis主线程的阻塞
7)使用物理机而非虚拟机部署Redis服务,使用高速固态盘作为AOF日志的写入盘。
8)使用分布式架构(主从复制、哨兵模式、集群)增加读写速度,并实现高可用
9)禁用内存大页(echo never > /sys/kernel/mm/transparent_hugepage/enabled),因开启内存大页会导致fork的速度变慢,也会拖慢写操作的执行时间

5.Redis的三大缓存问题

  • 正常情况下,大部分的访问请求应该是先被redis响应的,在redis那里得不到响应的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力是非常小的,且可以正常工作。
  • 缓存雪崩/穿透/击穿问题的根本原因在于redis缓存命中率下降,大量请求会直接发给MySQL数据库,导致MySQL数据库压力过大而崩溃。

缓存雪崩

  • redis中大量不同的缓存key集体过期

解决方案:使用随机数设置key的过期时间,防止集群过期
                  设置二级缓存
                  数据库使用排他锁,实现加锁等待

缓存穿透

  • 大量请求访问redis和MySQL数据库都不存在的资源

解决方案:对空值也进行缓存
                  使用布隆过滤器进行判断拦截一定不存在的无效请求
                  使用脚本实时监控,进行黑名单限制

缓存击穿

  • redis中一个热点key过期,此时又有大量请求访问这个热点key

解决方案:设置永不过期
                  预先对热点数据进行缓存预热
                  数据库使用排他锁,实现加锁等待

6.如何保证MySQL和redis的数据一致性

读取数据时,先从redis读取数据,如果redis没有,再从MySQL读取,并将读取到的数据同步到redis缓存中。
更新数据时,先更新MySQL数据,再更新redis缓存
删除数据时,先删除redis缓存,再删除MySQL数据
对于一些关键数据,可以使用定时任务,定时自动进行缓存预热,或使用MySQL触发器来实现同步redis缓存