zoukankan      html  css  js  c++  java
  • 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查询,会瞬间压倒数据库。

    正常的访问流程

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

    解决方案一

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

    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值、最后查询数据库将缓存结果回写到缓存、造成数据库压力过大

    分布式锁

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

  • 相关阅读:
    js5
    js4
    js(3)
    JS内容(2)
    html复习
    js介绍及内容(1)
    定位2
    position定位
    CSS
    列表及行块转变
  • 原文地址:https://www.cnblogs.com/surpass123/p/13376369.html
Copyright © 2011-2022 走看看