缓存击穿问题与缓存设置顺序原则

Posted RobotZhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缓存击穿问题与缓存设置顺序原则相关的知识,希望对你有一定的参考价值。

一、正确的缓存设置顺序:
1、读:先从DB读取之后,再写到cache中
2、更新:先更新 DB 中的数据,再删除 cache (必须是删除,而不是更新cache)
 
错误操作1,更新DB,同时写入cache
eg:进程A写了cache,此时进程B打断了A,又写cache,并写了DB,再次轮到进程A继续写DB,此时会导致,cache中保存的是B写入的数据,而DB中保存了A写入的数据,最终数据不一致,而且这个cache一直都是脏数据,如果此时不断有进程来读取,都是存在的cache脏数据;同理,如果先写DB,在写cache,一样存在可能被打断,最终导致cache是脏数据的问题
 
错误操作2,先删除cache,再更新DB,高并发时可能出现的问题:
eg:进程A先删除了cache,此时进程B打断A,则从DB中读取旧数据,并设置到了cache,再回来进程A更新DB,那么从这里开始,接下去所有的读请求,都是旧cache,脏数据
 
 
二、缓存“击穿”处理:
一个设置了过期时间的cache,在它过期那一刻,大量的并发请求会直连DB,DB负载过重问题。
解决办法:
1、当获取数据发现为空时,说明cache过期了,此时不马上连接DB,而是类似redis中的SETNX语法,设置一个tempkey=1,如果这个tempkey存在,则设置失败,不存在则设置成功, 设置成功,则进行DB读取数据,写入cache,否则延时30s,再次重试读cache,可能就有数据了。为什么这么做?因为多进程并发的时候,第一个发现cache失效了,设置了tempkey,进行DB读数据,其他进程则因为无法设置tempkey而等待一会,再读数据。
 1 def get_data(key=None):
 2 
 3     value = redis.get(key)
 4     if not value:
 5         #缓存失效
 6         if 1==redis.setnx(key+tempkey, 1, 60):   #设置一个临时key,如果被其他进程设置过了,则设置失败,也就不会连接db
 7             value = db.query(select name from test)
 8             redis.set(key, value)
 9             redis.delete(key+tempkey)
10 
11         else:
12             time.sleep(10)
13             get_data(key)  #递归重试,或许已经可以直接从cache中获取了
14     else:
15         return value

 

 
 

以上是关于缓存击穿问题与缓存设置顺序原则的主要内容,如果未能解决你的问题,请参考以下文章

Go分布式缓存 防止缓存击穿(day6)

数据库面试题——redis缓存穿透缓存击穿与缓存雪崩

缓存击穿、穿透、雪崩及Redis分布式锁

缓存击穿(内存 or Memcached or Redis.....)

Redis的缓存穿透缓存雪崩缓存击穿问题的概念与解决办法

Redis——缓存穿透缓存击穿缓存雪崩分布式锁