django接口缓存与Redis缓存存在问题

django接口缓存与Redis缓存存在问题

django接口缓存的示范

# 首页轮播图的缓存
def list(self, request, *args, **kwargs):
    """
    先从缓存中去取,没有查询数据库,同时返还一份给缓存保存;若缓存中有,直接将缓存中的值返回
    """
    banner_list = cache.get(settings.BANNER_LIST_CACHE)
    if not banner_list:
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        cache.set(settings.BANNER_LIST_CACHE, serializer.data,60*60)
        return Response(data=serializer.data)
    return Response(data=banner_list)

缓存雪崩,缓存穿透,缓存击穿

缓存穿透

# 查询一个数据库一定不存在的数据。正常缓存的使用流程是:先到缓存中查,如果缓存中没有,再去数据库中查,如果查询不到,则不放进缓存。

这就会造成一个严重的问题:如果黑客利用这个漏洞,往服务器发送大量的请求,使用不存在的key查询,会瞬间压倒数据库。

正常的访问流程

image-20200725112144814

但是如果Redis数据不存在,数据库数据也不存在,返回空,但是一般来说,空值是不会被写入Redis,如果反复请求同一条数据,则会发生缓存穿透的现象

解决方案一

# 如果查询数据的值为空值,设置个默认值,用Redis存储起来,不过设置的过期时间很短,如30秒

image-20200725114424756

def list(self,request,*args,**kwargs):
    query_res = cache.get(cachekey)
    if not query_res:
        query_res = self.get_object()
        if not query_res:
            cache.set(cachekey,'null',30)
            return Response(data='null')
        else:
            cache.set(cachekey,query_res,24*60*60)
            return Response(data=query_res)
    retrun Response(data=query_res)

但是,如果黑客,每次都使用不同步存在的key进行进行反问,还是会有造成缓存穿透的风险

解决思路:

可以中间件里面进行限制,对于存在大量异常请求的IP进行限制,直接返回

解决方案二:

采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定查询不到的数据会被这个bitmap给拦截掉,从而避免了对底层存储系统的查询压力。

缓存击穿

# 缓存击穿是指,一个key非常地热点,扛着超高的并发,当这个key失效的瞬间,持续的高并发就穿透了缓存,直接访问数据库,导致数据库瘫痪

解决方案:

业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

缓存雪崩

缓存雪崩是指,由于缓存层承载着大量请求,有效的保护了存储层,但是如果缓存层由于某些原因整体不能提供服务,于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
解决方案

保证缓存层服务高可用性

即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务,比如 Redis Sentinel 和 Redis Cluster 都实现了高可用。

依赖隔离组件为后端限流并降级

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

数据预热

可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

缓存并发

缓存并发是指,高并发场景下同时大量查询过期的key值、最后查询数据库将缓存结果回写到缓存、造成数据库压力过大

分布式锁

在缓存更新或者过期的情况下,先获取锁,在进行更新或者从数据库中获取数据后,再释放锁,需要一定的时间等待,就可以从缓存中继续获取数据。

猜你喜欢

转载自www.cnblogs.com/surpass123/p/13376369.html