缓存预热
缓存预热指提前将数据存到到缓存系统中,用户使用时直接查询缓存中的数据而不用走数据库。
如果MySQL中批量增加了100条数据,如何同步给Redis。
-
利用Redis的回写机制同步数据
什么也不做,当有用户访问数据但访问不到时,从数据库中查找到后存储到缓存中。可以在半夜发布代码,由工作人员作为用户来操作实现这种数据同步。
-
使用中间件自动处理
比如使用Canal,解析MySQL数据库日志,数据库新增一条数据,缓存中就新增一条数据。
-
程序自行完成
写个初始化程序,将已知的这批新增的数据同步到数据库中,上线后通过初始化程序进行数据同步。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,查询数据量巨大,请求直接落到数据库上,造成数据库压力过大甚至宕机。
缓存雪崩发生的原因可能是:
- Redis主机宕机,Redis全盘崩溃,偏硬件运维
- Redis中有大量key同时过期,大面积失效,偏软件开发
预防和解决方案:
-
Redis中的key设置为永不过期或者过期时间错开
一些关键的key可以设置为永不过期。过期时间错开,这样一个时间段内过期失效的键会少一些,失效后请求落到数据库上对数据库的压力也稍小一些。
-
Redis缓存集群实现高可用
-
主从 + 哨兵,哨兵节点监控到主节点宕机后,让从节点顶上来。
-
Redis Cluster,部署Redis集群,一个服务宕机,其他服务依然能正常使用。
-
开启Redis持久化机制AOF/RDB,尽快恢复缓存集群。
RDB是定期生成快照存入磁盘中,AOF是将写操作存入磁盘中。
RDB 是存放数据库中数据,适合做数据备份,但是数据可能不全,最近几分钟的数据可能没有。
AOF是每秒钟执行一次,如果有写操作的命令就存储起来,最多只会丢失1秒钟的数据,适合做数据恢复。
-
-
多缓存结合预防雪崩
使用本地缓存+Redis缓存,本地缓存是直接存储在内存中的,比如在代码中用一个映射对象存储数据。
-
服务降级
在客户端展示程序崩溃的界面,不再提供服务。
-
直接高价购买服务商提供的
缓存穿透
缓存穿透指的是恶意请求或者无效请求绕过缓存直接访问数据库,导致大量请求落到数据库上,增加了数据库的负担。
解决方案:
-
空对象缓存或缺省值
和业务部门商量一个缺省值,比如0,从MySQL中也查不到值的时候,让redis存入缺省值。用户请求的时候,直接从缓存返回缺省值而不用走MySQL。
这种情况无法解决黑客恶意攻击,当黑客伪造大量不存在的key时,每个key的查询都会走一遍MySQL。
-
使用布隆过滤器
布隆过滤器是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否存在于一个集合中。它的优点是空间效率和查询时间远远超过一般算法,缺点是有一定的误识别率和删除困难。
通过布隆过滤器将无效的key过滤掉,保证走到缓存和数据库的key通常是有效的。
查询key的时候,先通过布隆过滤器判断,如果key不存在就直接返回。如果key存在,再从Redis缓存中查,Redis缓存中没有数据在走MySQL数据器。
缓存击穿
缓存击穿指热点key失效,大量请求落到了数据库上,造成数据库压力过大。
热点key失效的原因:
- 到了过期时间自然清除但还是被访问到。
- 删除掉的key,刚好又被访问到。
解决方案:
-
把key的过期时间错开,对于访问频繁的热点key,不设置过期时间。
-
使用双检加锁策略
第一次查询缓存,如果从缓存中查到数据就直接返回数据,没有查到数据时进行第二次查询缓存,如果从缓存中查到数据就直接返回数据,否则从数据库中查询数据,然后存储到缓存中。 可以查看《Redis和MySQL双写一致性》中的双检加锁部分。