Redis高可用之持久化

1.Redis高可用

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

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

2.redis持久化

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

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

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

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

RDB持久化:

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

RDB持久化是指在指定的时间间隔内将内存中当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),用二进制压缩存储,保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据

工作流程:redis父进程会fork子进程来进行RDB持久化快照保存内存数据到硬盘里,文件名:dump.rdb
手动触发:bgsave命令 
自动触发:满足配置文件中 save n m 的规则(在n秒内发生了m次数据更新就会自动触发);主从复制在做全量复制时;执行shutdown命令关闭数据库时。

优缺点:RDB持久化保存的文件占用空间较小,网络传输快,恢复速度比AOF更快,性能影响比AOF更小;实时性不如AOF,兼容性较差,持久化期间在fork子进程时会阻塞redis父进程
 

AOF持久化:

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

RDB持久化是将进程数据写入文件,而AOF持久化,则是将Redis执行的每次写、删除命令记录到单独的日志文件中,查询操作不会记录; 当Redis重启时再次执行AOF文件中的命令来恢复数据。
与RDB相比,AOF的实时性更好,因此已成为主流的持久化方案。

Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置;

vim /usr/local/redis/conf/redis.conf
--1380行--修改,开启AOF
appendonly yes
--1407行--指定AOF文件名称
appendfilename "appendonly.aof"
--1505行--是否忽略最后一条可能存在问题的指令
aof-load-truncated yes
 
systemctl restart redis-server.service

AOF的执行流程包括:

 命令追加(append):将Redis的写命令追加到缓冲区aof_buf;
文件写入(write)和文件同步(sync):根据不同的同步策略将aof_buf中的内容同步到硬盘;
文件重写(rewrite):定期重写AOF文件,达到压缩的目的。

优缺点:实时性比RDB更好,支持秒级持久化,兼容性较好;持久化保存的文件占用空间更大,恢复速度更慢,性能影响更大,AOF文件重写期间在fork子进程时也会阻塞redis父进程,且IO压力更大

RDB和AOF的区别:

rdb是定时的将redis内存数据快照压缩保存在硬盘里面,一个是实时追加的方式将redis写操作命令记录到aof文件里,RDB的实时性没有AOF好,RDB保存文件占用空间更小,RDB恢复速度更快,AOF兼容性比RDB更好点,AOF持久化在文件重写期间IO压力比较大。

redis性能管理:

查看Redis内存使用

查看Redis内存使用:
info memory
  1. mem_fragmentation_ratio:内存碎片率。
  2. used_memory_rss:是Redis向操作系统申请的内存。
  3. used_memory:是Redis中的数据占用的内存。
  4. used_memory_peak:redis内存使用的峰值。

内存碎片如何产生的?

Redis内部有自己的内存管理器,为了提高内存使用的效率,来对内存的申请和释放进行管理。
Redis中的值删除的时候,并没有把内存直接释放,交还给操作系统,而是交给了Redis内部的内存管理器。
Redis在申请内存的时候,先看自己的内存管理器中是否有足够的内存可用。
Redis的这种机制,提高了内存的使用率,但是会使Redis中有部分自己没在用,却不释放的内存,导致了内存碎片的发生。

跟踪内存碎片率对理解Redis实例的资源性能是非常重要的:

内存碎片率 = 已分配的内存 / 实际使用的内存

内存碎片率在1到1.5之间是正常的,这个值表示内存碎片率比较低,也说明Redis没有发生内存交换。
内存碎片率超过1.5,说明Redis消耗了实际需要物理内存的150%,其中50%是内存碎片率。
内存碎片率低于1的,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换。需要增加可用物理内存或减少Redis内存占用。

Redis4.0版本开始,可以在不重启的情况下,线上整理内存碎片。
config set activedefrag yes     #自动碎片清理,内存就会自动清理了。
memory purge                    #手动碎片清理
注:由于内存碎片清理是redis主线程执行的,会发生阻塞。因此需要合理配置对应的参数和方式,保证redis的高性能。
 

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的速度变慢,也会拖慢写操作的执行时间
 

redis的三大缓存问题:

正常情况下,大部分的访问请求应该是先被redis响应的,在redis那里得不到响应的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力是非常小的,且可以正常工作。

缓存雪崩/穿透/击穿问题的根本原因在于redis缓存命中率下降,大量请求会直接发给MySQL数据库,导致MySQL数据库压力过大而崩溃。

1.缓存雪崩:redis中大量不同的缓存key集体过期

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

2.缓存穿透:大量请求访问redis和MySQL数据库都不存在的资源

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

3.缓存击穿:redis中一个热点key过期,此时又有大量请求访问这个热点key

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

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

先更新数据库,然后再删除缓存 + 缓存做过期时间,数据过期后再有读请求可从数据库直接更新缓存

(1)读取数据时,先从Redis中读取,如果Redis中没有,再从MySQL中读取,并将读取到的数据写入到Redis缓存中。这样,下次读取该数据时就可以从Redis中直接获取,避免了直接访问MySQL数据库,提高了读取速度。
(2)更新数据时,先更新MySQL数据库,再更新Redis缓存。这样,即使Redis缓存出现了异常,MySQL中的数据仍然是正确的,避免了数据不一致的问题。如果Redis更新失败,可以选择记录日志并进行重试,直到更新成功为止。
(3)删除数据时,需要先删除Redis缓存,再删除MySQL数据库。这样可以保证删除操作的原子性,避免了数据不一致的可能。
(4)对于一些关键数据,可以使用MySQL的触发器(Trigger)来实现同步更新Redis缓存。当MySQL中的数据发生变化时,触发器可以自动将变化同步到Redis中,避免了手动操作的疏漏。
(5)定期同步MySQL和Redis中的数据,以确保数据的一致性。可以使用定时任务或者其他方式定期同步两个数据源中的数据,从而保持一致。

需要注意的是,在实现数据一致性的过程中,需要考虑多种异常情况,如网络故障、Redis缓存出现问题等保证数据的正确性和完整性。

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值