Basic Redis Usage Example Part 3: Cache management in Python using Redis
Introduction
Effectively manage cache using Redis with python
In our last article, we discussed PUB/SUB pattern, now we will take a look at the possibilities of utilizing to Redis to leverage cache management in your python-based projects. Before we begin I would like to briefly tell about cache first.
What is Cache?
A cache is a temporary place to store something temporarily or you can say that where instructions are kept so that the performance of the processor can be accelerated all time. It is basically a high-speed access area that can be reserved section of main memory or storage device.
Advantage of Cache
Cache memory is faster than the main memory because processors can access cache faster than any other memory. In other words, the requested data doesn’t have to be bussed over to the processor. Cache reduces CPU idle time hence, it is perfect for CPU Utilization.
Use of Cache in Python Project
Cache is very useful for optimizing python code for better performance. Let me explain with a simple python example:
1 2 3 4 5 6 7 8 9 | def rfactorial(n): if n == 1: return n else: return n * rfactorial(n-1) |
This is a recursive factorial function that calculates nth factorial. Now, if we pay attention we will notice that, this function is doing some redundant calculation.
1 2 3 4 5 6 7 8 9 10 11 12 | import redis r = redis.connect(host='localhost', port=6379, db=0) r.hmset('fact_memroy', {0: 1, 1: 1, 'max': 1}) def my_fact(num): fact_memory = r.hgetall('fact_memroy') if num <= fact_memory['max']: return fact_memory[num] for x in range(fact_memory['max']+1, num+1): fact_memory[x] = fact_memory[x-1] * x fact_memory['max'] = num r.hmset('fact_memroy', fact_memroy) return fact_memory[num] |
The above solution is using Redis as a cache to store the factorials to escape redundant calculations. Note that, redis is not mandatory for such a trivial problem usually you can get away with a simple dict for example. However, with this example, we get introduced with redis one of the very useful command HMSET. This command lets user to set value of multiple keys at once! To retrieve all these values we can use hgetall
Redis Cache in Django Web Apps
Redis can also be used as Cache storage in Django Web Applications. Python’s one of the most iconic web frameworks Django is very popular among Pythonistas. Tech Giants like Instagram, Bitbucket, Quora and various others use Django in production. Although, Django has the ability to provide powerful performance, proper cache management becomes a must to scale the app according to the growth. Integrating Redis Cache is quite simple. It can be done with minimal changes to the code base. For example, let’s demonstrate a minimalist example of cache-based optimization in Django.
For the sake of simplicity, I’m assuming you have all the necessary dependencies installed i.e. django, redis, etc. The first thing you would like to do is define a couple of variables inside the ‘proj/settings.py’
1 2 3 4 5 6 7 8 9 10 | CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient" }, "KEY_PREFIX": "example" }} CACHE_TTL = 5 * 60 # 5 minutes |
The first variable tells Django we want to use Redis as our Cache Storage. And, the second variable sets Time to Live for the cache. I.e. the cache files will be refreshed after every 5 minutes. You can set it as your preference if your content doesn’t change much you can even set it longer.
Now, find the most frequently used views of your Django application that has relatively static contents i.e. contents don’t change that frequently. Let’s say, home_view
in your core/views.py
is frequently used. In that case, to cache it we will have to edit the views.py file like below:
1 2 3 4 5 6 7 8 9 10 11 12 13 | from django.conf.settings import CACHE_TTL from django.shortcuts import render from django.views.decorators.cache import cache_page from .models import MyDataModel @cache_page(CACHE_TTL) def home_view(requests): # fetch super useful data from database data = MyDataModel.objects.all() return render(request, 'cookbook/recipes.html', { 'data': data, }) |
And, that’s it! The cache_page is a decorator that tells Django to cache this view for the seconds mentioned in the parameter (CACHE_TTL) Notice, that home_view has a query. Normally, the query gets executed every time someone visits the url of home_view. However, as we are caching it for 5 minutes duration all the users visits this page within this duration will see the cached result and, won’t hit the database except the first one! i.e. The first time a viewer visits the query will execute as usual but, rest of the views will be served from cache for 5 minutes. After 5 minutes if another visitor visits the query will execute again and refresh the existing cache. This way, the app will perform, way faster than before.
Conclusion
So far, we have seen a few demonstrations of how we can utilize Redis cache in our python script or, web application. When doing Cache Management always keep in mind that, Cache invalidation is considered one of the hardest problem in Computer Science. So, pay attention to all the details and beware of premature optimization. Before jumping right into optimization using Cache make sure your code are optimized in other ways to its level best.
Pilot the ObjectRocket Platform Free!
Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.
Get Started