Best way to cache RESTful API results of GET calls

后端 未结 5 1748
我在风中等你
我在风中等你 2020-12-24 02:34

I\'m thinking about the best way to create a cache layer in front or as first layer for GET requests to my RESTful API (written in Ruby).

Not every request can be ca

5条回答
  •  隐瞒了意图╮
    2020-12-24 03:05

    I’ve used redis successfully this way in my REST view:

    from django.conf import settings
    import hashlib
    import json
    from redis import StrictRedis
    from django.utils.encoding import force_bytes
    
    def get_redis():
        #get redis connection from RQ config in settings
        rc = settings.RQ_QUEUES['default']
        cache = StrictRedis(host=rc['HOST'], port=rc['PORT'], db=rc['DB'])
        return cache
    
    
    
    class EventList(ListAPIView):
        queryset = Event.objects.all()
        serializer_class = EventSerializer
        renderer_classes = (JSONRenderer, )
    
    
        def get(self, request, format=None):
            if IsAdminUser not in self.permission_classes:  # dont cache requests from admins
    
    
                # make a key that represents the request results you want to cache
                #  your requirements may vary
                key = get_key_from_request()
    
                #  I find it useful to hash the key, when query parms are added
                #  I also preface event cache key with a string, so I can clear the cache
                #   when events are changed
                key = "todaysevents" + hashlib.md5(force_bytes(key)).hexdigest()        
    
                # I dont want any cache issues (such as not being able to connect to redis)
                #  to affect my end users, so I protect this section
                try:
                    cache = get_redis()
                    data = cache.get(key)
                    if not data:
                        #  not cached, so perform standard REST functions for this view
                        queryset = self.filter_queryset(self.get_queryset())
                        serializer = self.get_serializer(queryset, many=True)
                        data = serializer.data
    
                        #  cache the data as a string
                        cache.set(key, json.dumps(data))
    
                        # manage the expiration of the cache 
                        expire = 60 * 60 * 2  
                        cache.expire(key, expire)
                    else:
                        # this is the place where you save all the time
                        #  just return the cached data 
                        data = json.loads(data)
    
                    return Response(data)
                except Exception as e:
                    logger.exception("Error accessing event cache\n %s" % (e))
    
            # for Admins or exceptions, BAU
            return super(EventList, self).get(request, format)
    

    in my Event model updates, I clear any event caches. This hardly ever is performed (only Admins create events, and not that often), so I always clear all event caches

    class Event(models.Model):
    
    ...
    
        def clear_cache(self):
            try:
                cache = get_redis()
                eventkey = "todaysevents"
                for key in cache.scan_iter("%s*" % eventkey):
                    cache.delete(key)
            except Exception as e:
                pass
    
    
        def save(self, *args, **kwargs):
            self.clear_cache()
            return super(Event, self).save(*args, **kwargs)
    

提交回复
热议问题