阅读 273

redis三大问题|8月更文挑战

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

前言

在系统开发过程中,为了保护mysql,防止大量的请求导致mysql宕机等。基于内存的数据库redis,能够承担更大的并发量。所以在业务层与数据库层之间充当缓存层。即使如此,一旦出现以下问题,依然会造成数据库增压或宕机。

正常访问顺序:业务层 ==》缓存 ==》数据库

一、缓存穿透

1.1 问题描述

业务逻辑发送查询请求,首先从缓存中查询,由于缓存不存在,然后再前往数据库中查询。发现数据库中也没有该条记录,然后返回 null。这就是缓存穿透,根本原因是因为查询不存在的数据。 核心:查询缓存和数据库,二者皆不存在的数据。

1.2 危害

如果存在海量请求,访问不存在的数据,那么就会有海量请求访问数据库,最终会导致数据压力倍增或者系统崩溃。

1.3 为什么发生缓存穿透

  1. 恶意攻击,故意营造大量不存在的数据请求服务器,由于缓存中并不存在这些数据,导致大量的请求均落在数据库中,从而导致数据库崩溃。
  2. 代码逻辑错误,开发时需注意!!!

1.4 解决方案

(1) 缓存空数据
将数据库查询为空的key也存储在缓存中(集合返回为{},而非null),设置一个较短的过期时间,让其自动剔除。=》解决缓存中存在大量的空对象,内存占用问题
如果在缓存中空数据未过期时,插入一条记录,则会导致缓存层与存储层数据不一致的现象 ==》此时可以删除缓存中的空对象
(2) 布隆过滤器(bitmap)
在业务层与缓存层之间加一层,布隆过滤器

正常访问顺序:业务层 ==》 布隆过滤器 ==》缓存 ==》数据库

当业务发送请求时,首先在布隆过滤器中判断key是否存在。若不存在,则说明数据库中也不存在该数据,因此缓存都不用查询,直接返回null。若存在,则继续执行后面的流程。
使用场景
第一种:适应于空数据的key数量有限,key重复请求概率较高的场景。
第二种:适用于空数据的key各不相同、key重复请求概率低的场景。

二、 缓存雪崩

2.1 问题描述

缓存的存在可以对数据库进行保护,抵挡大量的查询请求,从而避免数据库压力剧增或崩溃。如果缓存因某种原因发生宕机,那么原来大量可以被缓存处理的请求就会全部被数据库处理,此时会导致数据库处理不了,导致系统崩溃。这就是缓存雪崩。

2.2 解决方案

(1) 使用缓存集群,保证缓存高可用
(2) 使用Hystrix

防雪崩工具,通过服务熔断、降级、限流三个手段来降低雪崩发生后的损失。 Hystrix就是一个Java类库,它采用命令模式,每一项服务处理请求都有各自的处理器。所有的请求都要经过各自的处理器。处理器会记录当前服务的请求失败率。一旦发现当前服务的请求失败率达到预设的值,Hystrix将会拒绝随后该服务的所有请求,直接返回一个预设的结果。这就是所谓的“熔断”。当经过一段时间后,Hystrix会放行该服务的一部分请求,再次统计它的请求失败率。如果此时请求失败率符合预设值,则完全打开限流开关;如果请求失败率仍然很高,那么继续拒绝该服务的所有请求。这就是所谓的“限流”。而Hystrix向那些被拒绝的请求直接返回一个预设结果,被称为“降级”。

三、缓存击穿

3.1 问题描述

热点数据集中失效,导致海量请求进入数据库重建缓存,这个过程可能数据库处理不了那么多请求,导致系统崩坏。

3.2 解决方案

(1)互斥锁
当第一个数据库查询请求发起后,就将缓存中该数据上锁;此时到达缓存的其他查询请求将无法查询该字段,从而被阻塞等待;当第一个请求完成数据库查询,并将数据更新值缓存后,释放锁;此时其他被阻塞的查询请求将可以直接从缓存中查到该数据。
互斥锁具有两个问题
第一个问题:降低系统的吞吐量
第二个问题:互斥锁可以避免某一个热点数据失效导致数据库崩溃的问题,而往往有一批热点数据同时失效的场景,此时如何防止数据库过载???===》将热点数据的过期时间错开(在基础时间上+随机数)
(2) 永不过期
存在数据一致性问题,代码复杂度会增大

文章分类
后端
文章标签