1、正确的缓存设置顺序:
一、读:先从DB读取以后,再写到cache中
二、更新:先更新 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,脏数据
2、缓存“击穿”处理:
一个设置了过时时间的cache,在它过时那一刻,大量的并发请求会直连DB,DB负载太重问题。
解决办法:
一、当获取数据发现为空时,说明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