问题一:aof文件过大


解决方案:

(1)使用BGREWRITEAOF命令(里面会有大部分是重复命令或者可以合并的命令(100次incr = set key 100)。

        aof重写机制的出现目的是给aof持久化文件瘦身,因为随着时间推移aof文件会变得越来越大。但是在aof文件内存储的字符指令实际上是可以进行合并重写的。

        经过几个月之后,发现还是存在aof文件过大的问题。所以,用定时任务来跑,不能解决根本问题。因为aof是记录了很多操作日志,就像Mysql的bin_log日志一样,体积比rdb方式持久化文件要大的多。

        理想情况下,aof的大小和当前内存使用的大小是一样的。

(2)混合持久化机制(在redis4.0之后是混合持久化机制,在4.0默认是关闭的,5.0之后默认是开启的)

        配置文件中通过aof-use-rdb-preamble参数控制,yes为开启no为关闭。

        混合持久化是通过bgrewriteaof完成的,不同的是当开启混合持久化时,folk出的子进程先将共享的内存副本全量以rdb方式写入aof文件,然后再将从写缓冲区增量命令以aof的方式写入文件,写入完成后通知主进程更新统计信息,并将新的含有rdb格式和aof格式的aof文件替换旧的aof文件。

简单而言,新的aof文件前半段是rdb格式的全量数据,后半段是aof格式的增量数据。

        优点:混合持久化结合了rdb和aof的优势,由于绝大多数都是rdb二进制格式,因此加载快,同时结合aof保存增量数据使得数据丢失少;

        缺点:兼容性差,一旦开启混合持久化,那么4.0之前的版本都不能识别这个混合持久化文件,同时前半段包含rdb二进制格式会导致阅读性差。

        混合持久化机制的过程:当进行aof重写时,对于历史数据则以rdb方式重新存储到aof文件中,重写完成后的数据还是以aof方式存储到aof文件中,因此也可以对aof文件进行瘦身。

问题二:如何保持mysql和redis中数据的一致性?


解决方案:

步骤一:想要提高应用的性能,可以引入缓存来解决。当缓存中不存在,从数据库中查+重建缓存。

步骤二:引入缓存后需要考虑缓存和数据库一致性问题,可选方案有“更新数据库+更新缓存”、“更新数据库+删除缓存

但更新缓存在并发情况下会引发数据一致性问题

例子:线程A和线程B两个线程,需要更新同一个数据,会发生这样的场景,

(1)线程A更新数据库(X=1)

(2)线程B更新数据库(X=2)

(3)线程B更新缓存(X=2)

(4)线程A更新缓存(X=1)

最终X的值在缓存中是1,在数据库中的是2,发生不一致

更新数据库+更新缓存方案,在并发场景下无法保证缓存和数据一致性,解决方案是加分布锁,但这种方案存在缓存资源浪费和机器性能浪费的情况

因此在并发环境中尽量少使用更新缓存,而是使用删除缓存。

步骤三:删除缓存也有两种方案,“先删除缓存,后更新数据库”、“先更新数据库,后删除缓存”:

先删除缓存,后更新数据库”:当发生[读+写]并发时,还是存在数据不一致的情况

先更新数据库,后删除缓存”:也会存在数据不一致的情况,但概率非常小(更新数据库+删除缓存的时间,要比读数据库+写缓存时间短),建议采用这种方案

步骤四:如何保证两步都成功执行(保证第二步执行成功即可)

解决方案是重试

第一种是通过消息中间件。如果在执行失败的线程中一直重试,还没等执行成功,此时项目重启了,那么这次重新请求也就丢失了,那这条数据就不一样了,用消息中间件可以保证

redis 文件大小限制 redisaof文件过大怎么处理_数据库

 第二种是订阅数据库变更日志,再操作缓存。当一条数据发生修改的时候,MySQL就会产生一条变更日志(BinLog),我们可以订阅这个日志,拿到具体操作的数据,然后再根据这条数据,去删除对应的缓存。

redis 文件大小限制 redisaof文件过大怎么处理_redis_02

订阅日志变更,目前也有比较成熟的开源中间件,例如阿里的canal,但与此同时,我们需要投入精力去维护canal的高可用和稳定性

步骤五:采用“先更新数据库,再删除缓存”方案,“读写分离+主从库延迟”也会导致缓存和数据库不一致.

缓解此问题的方案是延迟双删,过一会再删除(等从库更新完)

凭借经验发送延迟消息到队列中,延迟删除缓存,同时也要控制主从库延迟,尽可能降低不一致发生的概率

  Redis讲解目录:

Redis(1)-基本概念及使用

Redis(2)-Redis的一些问题及策略

Redis(3)-集群:主从复制、哨兵模式、Cluster

Redis(4)-Redis遇到的问题