🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[toc] ### 1-缓存穿透 缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。举个例子:某个黑客故意制造我们缓存中不存在的 key 发起大量请求,导致大量请求落到数据库。 #### 如何避免缓存穿透? 1. 最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。 2. 缓存无效 key。 3. 布隆过滤器。把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。 ![](https://img.kancloud.cn/7f/18/7f18af2a201251962cfd3ff474fe958f_626x758.png) ### 2-缓存雪崩 #### **1-什么是缓存雪崩?** 简介:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。 #### **2-有哪些解决办法?** **针对 Redis 服务不可用的情况:** 1. 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。 2. 限流,避免同时处理大量的请求。 **针对热点缓存失效的情况:** 1. 设置不同的失效时间比如随机设置缓存的失效时间。 2. 缓存永不失效。 ### 3-如何保证缓存和数据库数据的一致性? 缓存与数据库一致性问题Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删除 cache 。 如果更新数据库成功,而删除缓存这一步失败的情况的话,简单说两个解决方案: 1. **缓存失效时间变短(不推荐,治标不治本)**:我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。 2. **增加 cache 更新重试机制(常用)**: 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将 缓存中对应的 key 删除即可。 ### 4-Redis 内存淘汰机制了解么? > 相关问题:MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据? Redis 提供 6 种数据淘汰策略: 1. **volatile-lru(least recently used)**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选最近最少使用的数据淘汰 2. **volatile-ttl**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选将要过期的数据淘汰 3. **volatile-random**:从已设置过期时间的数据集(server.db\[i\].expires)中任意选择数据淘汰 4. **allkeys-lru(least recently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的) 5. **allkeys-random**:从数据集(server.db\[i\].dict)中任意选择数据淘汰 6. **no-eviction**:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧! 4.0 版本后增加以下两种: 7. **volatile-lfu(least frequently used)**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选最不经常使用的数据淘汰 8. **allkeys-lfu(least frequently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key