redis常见问题及解决方案

b6083fbd878e4475867d235739826d59.png

图片来源:缓存穿透,缓存击穿,缓存雪崩详解及解决办法[通俗易懂]-腾讯云开发者社区-腾讯云标题


 

1. 缓存雪崩

        指在同一时段大量的缓存失效,导致数据查询直接打到数据库,可能会使数据库崩溃。

解决方法:

设置合理的缓存失效时间,避免大量缓存同时失效。

实现缓存数据的分布式锁,确保同一时间只有一个客户端去数据库中查询数据,其他客户端等待。

利用Redis集群或者一致性哈希,分散key的分布,避免热点数据集中失效。

如果缓存数据设置了过期时间,可以在失效前主动更新缓存数据。

主从+哨兵、持久化机制 aof / rdb。

Hystrix 限流和降级:

Hystrix 通过线程池隔离依赖服务的调用,并提供了几种策略来控制流量:

线程池隔离:每个依赖服务都分配一个线程池,当请求的负载超过线程池设置的阈值时,新的请求会被立即拒绝,避免系统资源耗尽。

断路器模式:当某个服务的错误率达到一定比例时,自动开启断路器,之后对该服务的调用会直接失败,避免对服务进行不必要的重试。

// 使用HystrixCommand或HystrixObservableCommand来定义命令

HystrixCommand command = new HystrixCommand(arg1, arg2);

// 执行命令,如果失败或者开启了断路器,将会执行 fallback 方法

String result = command.execute();

Sentinel 限流和降级:

Sentinel 主要通过流量控制、熔断降级和系统保护规则来控制应用的资源使用和系统稳定性:

流量控制:可以根据负载和资源状态来限制流量,避免因为流量过大导致系统崩溃。

熔断降级:当依赖的服务出现不稳定(如响应时间超过阈值),自动触发熔断,停止对该服务的调用,并快速恢复。

系统保护:可以设置系统的负载保护阈值,当系统负载过高时自动过滤掉部分请求。

// 使用Sentinel API来定义资源

Entry entry = SphU.entry("resourceName");

try {

    // 业务逻辑

} finally {

    entry.exit();

}

// 或者使用try-with-resources自动释放

try (Entry entry = SphU.entry("resourceName")) {

    // 业务逻辑

}

Hystrix 和 Sentinel 都可以通过配置规则来实现限流和降级的功能,具体使用哪一个取决于你的项目需求和个人喜好。

 

2. 缓存击穿

        指一个缓存失效的key,高并发情况下,同一时刻有大量用户请求这一条数据,当这条数据在缓存中不存在时(即缓存未命中),大量的请求打到数据库,可能会使数据库崩溃。

缓存击穿与缓存雪崩有一定的区别。缓存雪崩是指许多数据同时过期,导致大量数据查询失败,从而造成数据库负载激增。而缓存击穿则是由于并发查同一条数据而导致数据库压力瞬间增大。

解决方法:

设置热点数据永不失效或者失效前主动更新。

使用分布式锁或者队列控制访问数据库的线程数量,避免大量并发请求打到数据库。

实现服务限流和熔断机制,防止因为某个服务不可用而影响整个系统。

3. 缓存穿透

        缓存穿透是指查询一个根本不存在的数据,缓存层和持久层都不会命中。在日常工作中出于容错的考虑,如果从持久层查不到数据则不写入缓存层,缓存穿透将导致不存在的数据每次请求都要到持久层去查询,失去了缓存保护后端持久的意义。

缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库。

bc64423fe055421998e78a10d88f5a25.png

标图片来源:缓存穿透,缓存击穿,缓存雪崩详解及解决办法[通俗易懂]-腾讯云开发者社区-腾讯云题

解决方法:

解决缓存穿透的方法主要包括使用布隆过滤器、‌缓存空值、‌以及使用锁机制。‌

布隆过滤器是一种数据结构,‌用于快速判断一个元素是否存在于一个集合中。‌它通过使用一个位数组和一组哈希函数来实现。‌当查询一个数据时,‌先判断该数据是否存在于布隆过滤器中,‌如果存在则直接返回结果,‌否则再从数据库中查询数据。‌这种方法可以有效拦截一定不存在的数据请求,‌减少对数据库的压力。‌布隆过滤器的优点是空间效率和查询时间都较高,‌但缺点是有一定的误识别率和删除困难。‌

缓存空值是指在查询结果为空时,‌也将结果进行缓存,‌但设置一个较短的过期时间。‌这样在接下来的一段时间内,‌如果再次请求相同的数据,‌就可以直接从缓存中获取,‌而不是再次访问数据库。‌这种方法简单易实现,‌可以很好解决缓存穿透问题,‌但会存在一些弊端,‌如短时间内大量恶意请求可能导致缓存系统内存占用过大。‌

使用锁机制可以避免多个相同的请求同时访问数据库。‌当一个请求发现缓存不存在时,‌可以使用锁机制来保证只有一个请求去加载数据,‌其他请求等待。‌这种方式可以解决数据库压力过大的问题,‌但可能会增加用户等待时间,‌且存在“误杀”现象,‌即当缓存中不存在但数据库中存在时,‌也会导致等待。‌

综上所述,‌解决缓存穿透的方法各有利弊,‌实际应用中需要根据具体场景和需求选择合适的方法或组合使用多种方法以达到最佳效果。‌

4. 过期策略

Redis的过期策略主要包括三种:‌定时过期、‌惰性删除和定期删除。这些策略共同作用,帮助管理Redis中的数据,确保数据的时效性并优化内存使用。以下是每种策略的详细解释:

‌定时过期‌:这种策略在设置键值对时同时指定一个过期时间。一旦超过这个时间,键值对就会自动被删除。这种策略可以确保数据的实时性,但效率不高,因为Redis需要为每一个设置了过期时间的键维护一个定时器。在大规模的键值对过期时,会创建大量的定时器,对CPU资源造成较大压力,影响服务器的响应时间和吞吐量。‌

‌惰性删除‌:这种策略在访问一个键时,如果发现这个键已经过期,那么Redis会立即删除这个键。这种策略可以避免不必要的定时器开销,但如果一个键在过期后长时间没有被访问,那么这个键会一直占用内存,直到被访问或者被其他删除策略处理。这对服务器的性能非常友好,但可能会留下一些垃圾数据占用内存。‌

‌定期删除‌:Redis会定期扫描一定数量的键,并删除其中的过期键。这种策略是惰性删除的补充,可以保证过期的键最终会被删除,但也会带来一定的性能消耗。为了不影响Redis的性能,通常会控制扫描的频率和数量。‌

除了上述三种主要策略外,Redis还提供了多种内存淘汰策略,如“‌volatile-lru”和“allkeys-lru”,这些策略在内存使用达到上限时会进行键的淘汰,其中一些策略会考虑键的过期时间。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

运行时异常

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值