缓存穿透
描述: 查询数据库中不存在的数据, 高并发的情况下, 压力集中在数据库
解决方案:
1) 将空值 Null 也放入数据库, 设置过期时间较短.
2) 布隆过滤器 https://segmentfault.com/a/1190000015482091
缓存雪崩
描述: 缓存中大量的 key 同时过期, 导致请求直接到了数据库.
解决方案:
1) 分开缓存的时间, 避免同时有大量的 key 过期.
缓存击穿
描述: 某个 key 在即将过期时有大量的请求, 当 key 过期时, 所有的请求通过了缓存直接到达了数据库
解决方案:
1) 缓存加锁, 如果 key 不存在就加锁, 然后查询数据库, 其他相同请求, 如果发现有锁则等待, 等到解锁在查询数据.
数据库与缓存一致性
描述: 场景一: 当更新数据时, 如更新某商品的库存, 当前商品的库存是 100, 现在要更新为 99, 先更新数据库更改成 99, 然后删除缓存, 发现删除缓存失败了, 这意味着数据库存的是 99, 而缓存是 100, 这导致数据库和缓存不一致.
解决方案:
1) 先删缓存, 删缓存成功, 再删数据库数据. 缓存删除失败, 则不删数据库.
描述: 场景二: 一个数据的修改还未提交到数据库, 但是缓存数据已经被删除了. 这个时候, 如果有一个查询过来, 则旧数据又被加入到缓存了. 在这个缓存过期之前, 请求的都是旧数据
解决方案: 网上给出的解决方案::: 遇到这种情况, 可以用队列的去解决这个问, 创建几个队列, 如 20 个, 根据商品的 ID 去做 hash 值, 然后对队列个数取摸, 当有数据更新请求时, 先把它丢到队列里去, 当更新完后在从队列里去除, 如果在更新的过程中, 遇到以上场景, 先去缓存里看下有没有数据, 如果没有, 可以先去队列里看是否有相同商品 ID 在做更新, 如果有也把查询的请求发送到队列里去, 然后同步等待缓存更新完成.
这里有一个优化点, 如果发现队列里有一个查询请求了, 那么就不要放新的查询操作进去了, 用一个 while(true) 循环去查询缓存, 循环个 200MS 左右, 如果缓存里还没有则直接取数据库的旧数据, 一般情况下是可以取到的.
来源: http://www.bubuko.com/infodetail-3110212.html