揭秘Redis数据丢失与一致性难题

创始人
2024-12-31 05:18:12
0 次浏览
0 评论

Redis数据丢失问题

曾经有朋友问我,为什么我们生产环境中的Redis经常丢失一些数据?一旦写入,一段时间后它可能会消失。
天哪,如果你问这个问题,那就说明你对Redis毫无用处。
Redis是一个缓存,你把它当作存储吧?什么是缓存?使用内存作为缓存。
内存是无限的吗?相反,内存是宝贵且有限的,而磁盘是廉价且充足的。
一台机器可能有几十GB的内存,但它可能有几TB的磁盘空间。
Redis主要依靠内存来进行高性能、高并发的读写操作。
那么,由于内存有限,例如,redis只能使用10GB,如果向其中写入20GB数据,您会怎么做?当然,10GB的数据将被销毁,那么10GB的数据将被保留。
那么哪些数据应该被删除呢?保存什么数据?当然,我们需要去掉很少使用的数据并保留常用的数据。
所以这就是缓存最基本的概念。
要么你自己设置超时,要么Redis自己杀死它们。
例如:setkeyvalue过期时间(1小时)设置的key会在1小时后消失,失效(1)设置过期时间,我们在设置key的时候可以给一个过期时间,就是过期时间,指定这个钥匙。
例如,它只能存活一个小时吗?10分钟?这非常有用。
我们可以指定缓存过期就过期。
如果您假设已将密钥批次配置为仅存活一小时,那么Redis如何在下一小时后删除该密钥批次?答案是:定期删除+惰性删除所谓定期删除是指redis默认情况下每隔100ms随机选择某些设置了过期时间的key,检查它们是否过期,过期则删除。
假设Redis中有10万个key,并且设置了过期时间。
如果你每隔几百毫秒检查100,000个键,Redis基本上就会死掉,CPU负载会非常高,这将被你的检查所消耗。
已到期。
请注意,这里我们不会以每100毫秒超时的方式迭代所有键,这将是性能灾难。
事实上,Redis每100毫秒随机选择某些键来检查和删除它们。
但问题是,定期删除可能会导致很多过期的key在定时器到期时没有被删除。
那么,我们应该做什么呢?于是就懒得删了。
延迟删除是指当你获取一个key时,如果设置了过期时间,Redis会检查该key是否过期?如果过期,它将被删除,并且不会向您返还任何内容。
所以并不是时间到了之后该key就被删除了,而是当你查询该key时,Redis又懒惰的检查了一遍。
使用以上两种方法,可以保证过期的key被删除。
这很简单。
也就是说,你的过期key并没有被定期删除删除,它仍然保留在内存中并占用你的内存,除非你的系统检查该key,否则它会被Redis删除。
但事实上,还是有一个问题。
如果定期删除遗漏了大量过期密钥并且您没有在以下位置检查它们:时间,那么你没有使用惰性删除,那个时候会发生什么?如果内存中堆积了大量过期key,导致Redis内存块耗尽,怎么办?答案是:采用内存处置机制。
(2)内存剔除如果Redis内存占用空间过多,此时就会进行内存剔除。
有以下一些策略:1)noeviction:当内存不足以容纳新写入的数据时。
新的写操作会报错。
平时没人用,真是恶心。
2)allkeys-lru:当内存不够容纳新写入的数据时,在key空间中,移除最近最少使用的key(也是最常用的)3)allkeys-random:当内存不够时为了容纳新写入的数据,在key空间中,随机删除某个key。
一般不使用这个。
为什么它应该是随机的?您必须删除最近最少使用的密钥。
4)易失性-lru:当没有足够的内存容纳新写入的数据时,就会过期。
set在key时间空间中,移除最近最少使用的ke。
y(这个一般不适合)5)volatile-random:当内存不足以容纳新写入的数据时,随机删除键空间中的一个键,设置过期时间6)volatile-ttl:当内存不够时为了容纳新写入的数据,在设置了过期时间的键空间中,首先删除过期时间较早的键。
例如:redis中有10个key,现在淘汰策略集是allkeys-lru,redis需要。
删除。
确保您可以继续写作的几个关键。
这10个键中,1个键在最近1分钟被查询100次,1个键在最近10分钟被查询50次,1个键在最近1小时被查询1次。
可以肯定的是,那些最近最少使用的人都被杀死了。
为什么Redis中存储的数据有时会丢失?这很简单。
你写入的数据太多,内存已满,或者触发了某个条件,比如redisallkeys-lru内存处置策略,它会自动清理一些最近使用过、很少使用的数据。

Redis与MySQL数据一致性问题

Redis具有高性能的数据读写功能,广泛应用于缓存场景。
首先,它可以提高业务系统的性能。
其次,能够承受数据库的高并发流量请求。
点我->解密Redis为什么这么快的秘密。

使用Redis作为缓存组件时,需要防止以下问题,否则可能会造成生产事故。

Redis缓存满了怎么办?

如何解决缓存穿透、缓存击穿、缓存雪崩?

Redis数据过期后会立即删除吗?

Redis突然变慢的问题如何排查解决?

如何处理Redis和MySQL之间的数据一致性问题?

在本文正式开始之前,我认为我们需要就以下两点达成共识:

缓存必须有过期时间;

保证数据库和缓存的最终一致性就足够了,不需要追求强一致性。

目录如下:

什么是数据库和缓存一致性

缓存使用策略

2.1Cache-Aside(绕过缓存)

2.2Read-Through(直接读取)

2.3Write-Through同步直接编写

2.4Write-Behind

绕过缓存下的一致性问题分析

3.1先更新缓存,再更新数据库

3.2先更新数据库,再更新缓存

3.3先删除缓存,再更新数据库

3.4先更新数据库,再删除缓存

一致性解决方案有哪些?

4.1缓存延迟双重删除

4.2删除缓存重试机制

4.3读取binlog异步删除

总结

1.什么是数据库和缓存一致性?

数据一致性是指:

缓存中有数据,缓存数据值=数据库中的值;

缓存中没有数据。
数据,数据库中的值=最新值。

反向缓存与数据库不一致:

缓存数据值≠数据库中的值;

缓存或数据库中存在旧数据,导致线程读取旧数据。

为什么会出现数据一致性问题?

使用Redis作为缓存时,当数据发生变化时,我们需要双写来保证缓存与数据库中的数据一致。

数据库和缓存毕竟是两个系统。
如果我们要保证强一致性,就必须引入2PC或者Paxos等分布式一致性协议,或者分布式锁等,这是很难实现的,肯定会对性能产生影响。

如果对数据一致性的要求真的这么高,真的有必要引入缓存吗?

2.缓存使用策略

在使用缓存时,通常有以下几种缓存使用策略来提高系统性能:

Cache-AsidePattern(绕过缓存,业务系统中常用)

Read-ThroughPattern

Write-ThroughPattern

Write-BehindPattern

2.1Cache-Aside

所谓“绕过缓存”是指读缓存、读数据库、更新缓存的操作都是在应用系统中完成的,是业务系统中最常用的缓存策略。

2.1.1读取数据

读取数据的逻辑如下:

当应用程序需要从数据库读取数据时,首先检查是否存在缓存的数据被命中。

如果缓存未命中,则查询数据库获取数据,并将数据写入缓存,以便后续读取相同数据都会命中缓存,最后将数据返回给缓存呼叫者。

如果缓存命中,则直接返回。

时序图如下如下:

绕过缓存读取时序图

优点

缓存只包含应用程序实际请求的数据。
有助于保持缓存大小的成本效益。

实现简单,可以提高性能。

实现的伪代码如下:

String?cacheKey?=?"公众号:码哥字节";String?cacheValue?=?redisCache.get(cacheKey);//缓存hitif?(cacheValue?!=?null)?{return?cacheValue;}?else?{//缓存丢失,?从数据库获取数据cacheValue?=?getDataFromDB();//?写入数据到cacheredisCache.put(cacheValue)}缺点

由于数据是在缓存未命中后才加载到缓存中的,所以初次调用的数据请求响应时间增加了一些开销由于需要额外的缓存填充和数据库查询时间。

2.1.2更新数据

使用“cache-aside”模式写入数据时,流程如下。

绕过缓存写入数据

将数据写入数据库;

使缓存中的数据失效或者更新缓存data;

使用cache-aside时,最常见的写入策略是直接将数据写入数据库,但缓存可能与数据库不一致。

我们应该为缓存设置一个过期时间。
这是确保最终一致性的解决方案。

如果过期时间太短,应用程序将不断从数据库中查询数据。
同样,如果过期时间太长,在没有使缓存失效的情况下更新缓存,则缓存的数据很可能是脏的。

最常见的方式是删除缓存,使缓存数据失效。

为什么不更新缓存?

性能问题

当缓存更新成本较高,需要访问多个表进行联合计算时,建议直接删除缓存,而不是更新缓存数据,以保证一致性。

安全问题

在高并发场景下,查询到的数据可能是旧值。
码哥稍后会详细分析,不用担心。

2.2Read-Through(直读)

当缓存未命中时,数据也会从数据库中加载,写入缓存并返回给应用系统。

尽管直读和缓存端非常相似,但在缓存端中,应用程序负责从数据库检索数据并填充缓存。

Read-Through将获取数据存储中的值的责任转移给缓存提供者。

Read-Through

Read-Through实现了关注点分离的原则。
代码只与缓存交互,缓存组件管理自身与数据库之间的数据同步。

2.3Write-Through同步直写

与Read-Through类似,当发生写请求时,Write-Through将写职责转移给缓存系统,由缓存抽象层完成缓存数据的更新和数据库数据。
,时序流程图如下:

Write-Through

Write-Through的主要好处?优点是应用系统不需要考虑故障处理和重试逻辑。
,将其留给缓存抽象层来管理实现。

优缺点

直接单独使用该策略没有任何意义,因为该策略需要先写入缓存,再写入数据库,给写入操作带来了额外的延迟。

什么时候进行直写?与Read-Through?配合使用,Read-Through?的优点可以在保证数据一致性的同时得到充分利用,而无需考虑如何使缓存设置失效。

Write-Through

该策略颠倒了Cache-Aside中缓存填充的顺序,而不是在一次缓存后延迟加载到缓存中错过。
相反,数据是先写入缓存,然后缓存组件将数据写入数据库。

优点

缓存和数据库数据始终是最新的;

查询性能最好,因为要查询的数据可能已经写入缓存了。

缺点

不经常请求的数据也会写入缓存,导致缓存更大且更昂贵。

2.4Write-Behind

这张图乍一看好像和“Write-Through”一样,其实不然。
不同之处在于最后一个箭头的箭头:它从实线变成了线。

这意味着缓存系统会异步更新数据库数据,应用系统只会与缓存系统交互。

应用程序不必等待数据库更新完成,从而提高了应用程序性能,因为数据库更新是最慢的操作。

![图片]()

Write-Behind

这种策略下,缓存和数据库的一致性不强,对于具有高一致性不推荐。

3.旁路缓存下的一致性问题分析

Cache-Aside策略最常用于业务场景。
该策略下,客户端读取数据时先读取缓存,如果命中则返回;如果未命中,则从数据库中读取数据并写入缓存,因此读取操作不会导致缓存与数据库不一致。

关键点是,对于写操作,数据库和缓存都需要修改,而且两者之间会有顺序,可能会导致数据不再一致。
对于写入来说,我们需要考虑两个问题:

我们应该先更新缓存还是数据库?

当数据发生变化时,选择修改缓存(update)还是删除缓存(delete)?

将这两个问题组合起来,系列组合会有四种选择:

先更新缓存,再更新数据库;

先更新数据库,再更新数据库更新缓存;

先删除Cache,再更新数据库;

先更新数据库,再删除缓存。

你不需要死记硬背下面的分析。
关键是,在推演过程中,只需要考虑以下两种场景是否会导致严重问题:

其中,如果第一个操作成功,第二个操作失败,会出现什么问题?

高并发情况下读取数据会不一致吗?

为什么不考虑第一个失败第二个成功的情况呢?

你觉得怎么样?

由于第一个失败,因此无需执行第二个。
只要第一步直接返回50x等异常信息就可以了,不会出现不一致的问题。

只有第一个成功,第二个失败才让人头疼。
如果要保证它们的原子性,就涉及到分布式事务的范畴。

3.1先更新缓存,再更新数据库

![图片]()

先更新缓存,再更新数据库

如果缓存是先更新成功,写入数据库失败,会导致缓存是最新数据而数据库是旧数据,那么缓存就会是脏数据。

之后其他查询立即请求时就会得到这个数据,但是数据库中不存在这个数据。

对于数据库中不存在的数据,缓存并返回给客户端是没有意义的。

这个方案直接Pass。

3.2先更新数据库,再更新缓存

一切正常如下:

先写入数据库,成功;

再次更新缓存,成功。

更新缓存失败

此时我们来推断一下,如果这两个操作的原子性是destroy:如果第一步成功,第二步失败,会出现什么问题?

这会导致数据库有最新的数据,而缓存有旧的数据,造成一致性问题。

我不会画这张图。
和上图类似,只是交换Redis和MySQL的位置。

高并发场景

谢八哥经常做996,腰酸背痛,脖子也酸痛。
他写的bug越多,他写的就越多。
他想去按摩以提高他的编程技能。

受疫情影响,订单难求。
高端会所的技术人员争先恐后地接下这份订单。
兄弟,并发度很高啊。

进店后,前台将顾客信息录入系统,执行?setxx服务技师=待确定,初始值表示当前无人接待,保存到数据库和缓存,然后由技术人员安排按摩服务。

如下图:

![图片]()

高并发先更新数据库,再更新缓存

<没有。
98技术员首先行动,向系统发送命令“设置谢巴格的服务技术员=98”写入数据库。
此时系统网络波动卡顿,数据还没来得及写入缓存。

接下来,520号技术员也向系统发送“设置谢八哥的维修技术员=520”并写入数据库,同时也将这些数据写入缓存。

此时98号技术员之前的写入缓存请求开始执行,数据“谢巴格的服务技术员=98”成功写入缓存。

最后发现数据库值=?设置谢巴格维修技师=520,缓存值=?设置谢巴格维修技师=98。

缓存中520号技术员的最新数据被98号技术员的旧数据覆盖。

所以,在高并发场景下,如果多个线程写入如果同时写入数据然后写入缓存,就会出现缓存使用旧值和数据库使用最新值的不一致。

这个方案可以直接通过。

如果第一步失败,直接返回50x异常,不会出现数据不一致的情况。

3.3先删除缓存,再更新数据库

按照“兄弟代码”提到的套路,假设第一次操作成功,第二次操作失败,会发生什么情况?高并发场景下会发生什么?

第二步写入数据库失败

假设有两个请求:写请求A和读请求B。

写请求A第一步删除缓存成功。
如果写入数据库的数据失败,写入的数据将会丢失,数据库会保存旧值。

然后又一个读请求B进来,发现缓存不存在。
从数据库中读取旧数据并将其写入缓存。

高并发下的问题

![图]()

先删除缓存,再写入数据库

被98号技术员击中了第一的。
系统收到删除缓存数据的请求。
当系统即将将“设置小彩姬的服务技术员=98”写入数据库时​​,出现了延迟。
,来不及写了。

此时大堂经理向系统执行读取请求,查看小菜鸡是否有技术人员接收,以方便安排技术人员服务。
系统发现缓存中没有数据,于是从数据库中读取旧数据。
?设置小菜鸡维修技师=待定,写入缓存。

此时,原本卡住的98号技术员写入数据?设置小菜鸡的服务技师=98到数据库并完成操作。

这种情况下,缓存的数据将是旧数据,在缓存过期之前无法读取到最新的数据。
小菜鸡本来是98号技师点的,但大堂经理以为没人接待他。

这个方案通过了,因为第一步成功了,第二步失败了,会导致数据库有旧数据。
缓存中没有数据就会从数据库读取旧值写入缓存,导致数据不一致。
再来一张卡什。

无论是异常情况还是高并发场景,都会出现数据不一致的情况。
错过。

3.4先更新数据库,再删除缓存

经过前面三个解决方案,都通过了。
我们来分析一下最终的方案是否可行。

按照“套路”来判断异常和高并发会带来哪些问题。

这个策略可以知道,如果数据库写入阶段失败,会直接返回客户端异常,不需要进行缓存操作。

所以如果第一步失败,不会出现数据不一致的情况。

缓存删除失败

关键是第一步要把最新的数据写入数据库成功。
删除缓存失败怎么办?

您可以将这两个操作放在一个事务中。
当缓存删除失败时,回滚对数据库的写入。

不适合高并发场景,容易出现大事务,造成死锁问题。

如果不回滚,就会出现数据库无论是新数据、缓存还是旧数据,数据不一致的情况。
我应该怎么办?

所以,我们必须要想办法成功删除缓存,否则就只能等到有效期到期了。

使用重试机制。

比如重试3次,3次失败,日志就会记录到数据库中,可以使用分布式调度组件xxl-job来实现后续处理。

在高并发场景下,最好采用异步方式进行重试,比如向mq中间件发送消息,实现异步解耦。

或者可以使用Canal框架订阅MySQLbinlog日志,监听相应的更新请求,并执行相应缓存的删除操作。

高并发场景

我们来分析一下高并发读写的问题...

![图片]()

先写入数据库再写入删除缓存

98号技术员率先行动,接手了小彩姬的业务。
执行的数据库?设置小菜鸡维修技师=98;网络仍然卡住,没有时间执行缓存删除操作。

主管Candy向系统执行读取请求,检查小彩姬是否有技术人员接待他。
他发现缓存里有数据?小彩姬的服务技师=待定,直接将信息返回给客户。
主管认为没有人收到。

98号技术员原本接单,但因卡顿未能删除缓存。
现在删除成功了。

读请求可能会读取到少量的旧数据,但是旧数据很快就会被删除,后续请求就可以获取到最新的数据,所以没有什么大问题。

还有一种更极端的情况。
当缓存自动过期时,会遇到高并发读写的情况。
假设有两个请求,一个线程A做查询操作,一个线程B做更新操作。
操作,则会出现以下情况:

![图片]()

缓存突然过期

缓存过期时间过期,缓存失效。

线程A的读请求读取缓存,如果未命中,则查询数据库得到一个旧值(因为B会写入一个新值,相对来说是一个旧值),准备写入数据到缓存。
发送时出现网络问题。

线程B执行写操作,将新值写入数据库。

线程B执行缓存删除。

线程A继续,从滞后中醒来,并将查询到的旧值写入缓存。

马哥,你玩得怎么样,还是有不一致的地方。

不要惊慌,这种情况发生的可能性很小。
这几乎是微不足道的。
发生上述情况的必要条件是:

步骤(3)中对数据库的写操作比步骤(2)中的读操作更短且更快。
只有这样才能在步骤(4)之前执行步骤(5)。

缓存刚刚到期。

通常MySQL单机的QPS在5K左右,TPS在1k左右(ps:Tomcat的QPS在4K左右,TPS=1k左右)。

数据库的读操作比写操作要快很多(也正是因为如此,读写是分开的),所以步骤(3)很难比步骤(2)快。
同时,还需要配合缓存进行过期处理。

所以,在使用绕过缓存策略时,建议对于写操作:先更新数据库,再删除缓存。

4.一致性解决方案有哪些?

最后,对于Cache-Aside(绕过缓存)策略,当写操作采用先更新数据库再删除缓存时,我们来分析一下有哪些数据一致性解决方案?

4.1缓存延迟双删除

先删除缓存再更新数据库如何避免脏数据?

采用延迟双删除策略。

先删除缓存。

编写数据库。

休眠500毫秒,然后删除缓存。

这样最多只会发生500毫秒的脏数据读取时间。
关键是这个睡眠时间怎么确定?

延迟时间的目的是保证读请求结束,写请求可以删除读请求造成的缓存脏数据。

所以我们需要自己评估项目的数据读取业务逻辑的耗时,在读取耗时的基础上加上几百毫秒作为延迟时间。

4.2缓存删除重试机制

缓存删除失败怎么办?例如,延迟双删除第二次删除失败,则无法删除脏数据。

使用重试机制保证缓存删除成功。

例如重试3次,3次失败,就会将日志记录到数据库中,并发出警告,需要人工干预。

在高并发场景下,最好采用异步方式进行重试,比如向mq中间件发送消息,实现异步解耦。

重试机制

步骤(5)如果删除失败且未达到最大重试次数则消息将重新排队,直到删除成功。
否则会被记录在数据库中,需要人工干预。

这个方案有一个缺点,就是会导致对业务代码的侵入,所以接下来的方案是启动一个专门订阅数据库binlog的服务来读取需要删除的数据并执行缓存删除操作。

4.3读取binlog异步删除

binlog异步删除

更新数据库;

数据库会将操作信息记录在binlog中log;

使用canal订阅binlog日志获取目标数据和key;

缓存删除系统获取canal数据,解析目标key,尝试删除缓存。

如果删除失败,则将消息发送到消息队列;

缓存删除系统重新从消息队列中获取数据,再次执行删除操作。

总结

缓存策略的最佳实践是CacheAsidePattern。
它们分为读缓存最佳实践和写缓存最佳实践。

读缓存最佳实践:先读缓存,命中则返回;查询数据库,如果有缺失,则写入数据库。

写入缓存的最佳实践:

先写入数据库,再操作缓存;

直接删除缓存,不要修改,因为成本更新缓存的频率非常高,需要访问多个表进行联合计算。
建议直接删除缓存而不是更新。
另外,删除缓存很简单,副作用只是增加一个chachemiss。
建议您使用此策略。

在上述最佳实践下,为了尽可能保证缓存和数据库的一致性,我们可以使用延迟双删除。

为了防止删除失败,我们采用异步重试机制来保证删除的正确性。
借助异步机制,我们可以向mq消息中间件发送删除消息,或者使用canal订阅MySQLbinlog日志来监听写入请求来删除对应的缓存。

那么,如果我必须确保绝对一致性怎么办?我先给出结论:

没有办法做到绝对的一致性。
这是由CAP理论决定的。
缓存系统适用于非强一致性的场景,因此属于CAP中的AP。

所以,我们不得不妥协,但是要达到BASE理论中提到的最终一致性。

事实上,一旦在解决方案中使用了缓存,往往意味着我们放弃了数据的强一致性,但同时也意味着我们的系统在性能上可以获得一些提升。

这就是所谓的权衡。

原文:https://juejin.cn/post/7103701796429758478

Redis过期策略和回收策略

它是一种被动策略,当客户端访问密钥时,它会检查返回密钥是否过期,如果过期则立即删除。
Redis默认每秒会完成一百万次过期。
1.从缺失字典中随机选择20个键;2、删除这20个键中的确切键;扫描避免过度循环,导致序列卡住。
数据库服务器不会返回过期时间,数据库服务器会被动处理过期时间。
当key过期时,主库会在AOF文件中添加一条del指令,并配置所有从库。
从库会通过执行这个del命令来删除转义的key。
因为同步指令是异步执行的,如果主库中的del指令在从库的时候没有完成,那么主从库之间的数据就会不兼容。
返回过期策略为:定期删除+惰性删除。
所谓周期性删除,是指默认情况下,Redis每隔100ms随机选择一些过期的key,等待看它们是否过期,如果过期则将其删除。
假设有10万个key返回,并且设置了过期时间。
如果搜索100,000个键100,000秒,那么返回基本上会死掉,CPU负载会非常高,这会花在检查确切的键上。
cn.这里请注意,并非所有按键每100毫秒就会超时。
事实上,它返回随机选择一些每100磅的键来检查和删除它们。
但有可能会发现很多过期文件没有被定期删除,时间到了还没有删除。
于是就慢慢被毁掉了。
这就是说,当你拿到key之后,如果有设定的时间段的话,你就返回检查key是否已经过期了?如果过期,本次将被删除,并且不会向您退款。
但实际上,仍然存在问题。
如果定期删除需要很多过期的key,那么你没有及时检查,所以你不使用被动删除,这时候会发生什么呢?如果溢出的key数量在内存中累积,导致返回块内存被消耗,该怎么办?答案是:采用记忆消除机制。

3大问题!Redis缓存异常及处理方案总结

Redis作为一种高性能的内存数据结构存储系统,在日常开发中发挥着重要作用,广泛应用于缓存、计数器、消息队列、排名等场景。
其优点包括数据持久化、支持复杂数据结构存储、备份模式以及快速的读写速度,使其成为最流行的缓存解决方案之一。
然而,在实际应用中,Redis可能会遇到缓存雪崩、缓存故障、缓存入侵等异常情况,必须妥善处理,以避免系统崩溃和数据库负载增加。
###缓存雪崩缓存雪崩是指在短时间内向数据库同时发送大量请求,因为缓存中存储的所有数据都已过期。
这种情况通常发生在大量数据同时发生故障时,导致数据库负载迅速增加,严重时可能导致数据库崩溃。
解决缓存雪崩的方法包括限制过期次数、配置缓存过期分布以及使用缓存失效策略。
###CacheBreakdown缓存崩溃发生在高并发系统上。
在这个系统中,许多并发请求同时检索不在缓存中但在数据库中的数据。
这种情况往往是由于某些热点数据缓存过期造成的,缓存过期后,大量请求同时命中数据库。
解决缓存故障的解决方案包括使用互斥锁和为热点数据设置过期时间。
###CachePenetration缓存穿透是指请求访问的数据既不在缓存中,也不在数据库中,每次请求最终都是从数据库中查询,导致查询无效。
解决缓存入侵的策略包括使用漏桶算法、设置空值缓存过期时间以及增加数据验证。
###缓存预热和降级除了一般的例外之外,缓存预热和缓存降级也是优化策略。
缓存预热是指在系统上线之前将数据预先加载到缓存中,以避免用户发出请求时先查询数据库。
缓存降级是指在缓存故障或服务出现问题时,选择不访问数据库,防止系统雪崩,保证基本服务可用的手段。
###总结通过合理的设计和策略的实施,可以有效管理和预防Redis缓存异常,保证系统稳定高效运行。
理解并应用上述策略对于提高整体系统性能和用户体验非常重要。
热门文章
1
Redisson分布式锁深度解析:Red... Redis实现分布式锁+Redisson源码解析在某些场景下,多个进程需要以互斥...

2
深度解析Docker:容器技术提升应用部... docker是什么Docker是一种强大的开源容器技术,它将应用程序及其所有依赖...

3
C语言实现:如何判断一个整数是否为质数? C语言输入一个整数,判断是否是质数?#include//头文件intmain()...

4
K8s弃用Docker背后的故事及Doc... K8s为什么要弃用Docker?在讨论K8s抛弃Docker的话题时,我们首先需...

5
C语言文本输入输出教程:安全高效处理字符... C语言怎么变成文字?如果你想用C语言输入输出文本,其实很简单。您必须首先定义一个...

6
深入解析Java:面向对象编程特性与实现... Java语言的特点,实现机制和体系结构。中的任何实体都可以被视为一个对象。对象通...

7
三款免费Docker管理工具,提升您的可... 3款免费又好用的Docker可视化管理工具在Docker的世界里,命令行工具无疑...

8
C语言期末编程题解析:完整程序代码分享 C语言期末考试编程代码函数题?按照题目要求编写的完整程序如下(见图,图中重复的部...

9
轻松掌握:Redis键值查看技巧,两种方... 如何读取redis中的key值中的结果我们希望它能帮助您使用它。怎么查看redi...

10
SQL DELETE语句:详解及不同删除... 请问Sql的DELETE语句怎么写delete表示删除表中的数据示例:delet...