Bootstrap FreeKB - Flask - Getting Started with Redis Cache
Flask - Getting Started with Redis Cache

Updated:   |  Flask articles

Redis is a service that can be used to cache requests and queries, so that the time it takes for subsequent requests and queries is reduced.

Before getting into Flask caching with Redis, let's first demonstrate a Flask app with an endpoint that takes 5 seconds to return a response.

from flask import Flask
import time

app = Flask(__name__)

@app.route("/Delay")
def Delay():
    time.sleep(5)
    return "Hello World"

if __name__ == "__main__":
    app.run()

 

Each time we go to the /Delay endpoint, it should take 5 seconds for "Hello World" to be returned.

 

Let's use Redis to cache requests to the /Delay endpoint. Let's Install Redis on Docker.

Or you could create an Amazon Web Services (AWS) Redis serverless cluster which should give you a URL such as https://my-redis-cache-abc123.serverless.use1.cache.amazonaws.com:6379.

Or you could create an Amazon Web Services (AWS) Redis dedicated cluster which should give you a URL such as https://my-redis-cluster.abc123.clustercfg.use1.cache.amazonaws.com:6379.

If you go with installing Redis on Docker, the docker container ls command on your Docker system should return something like this which shows that Redis is up and running on port 6379.

~]$ sudo docker container ls
CONTAINER ID   IMAGE                          COMMAND                  CREATED          STATUS          PORTS                                                         NAMES
4cf2570d0f8f   redis:latest                   "docker-entrypoint.s…"   50 seconds ago   Up 49 seconds   0.0.0.0:6379->6379/tcp                                        redis

 

We will need to update our Flask app have the flask-caching and redis packages. For example, if running Flask in a UI such as VSCode, the pip install command can be used to install the flask-caching and redis packages.

pip install flask
pip install flask-caching
pip install redis

 

Or, if running Flask in a Docker container, you can create a Docker image from a Dockerfile that has the flask-caching and redis packages and then use the docker build command to create the Docker image.

FROM tiangolo/uwsgi-nginx-flask:latest
RUN apt-get update -y
RUN pip install --upgrade pip
RUN pip install requests
RUN pip install flask-caching
RUN pip install redis

 

Let's update main.py to include the Caching stuff, replacing CACHE_REDIS_HOST with the IP address or DNS hostname of your Docker system or the AWS URL.

from flask import Flask
import time
from flask_caching import Cache

app = Flask(__name__)

app.config['CACHE_TYPE'] = 'redis'
app.config['CACHE_REDIS_HOST'] = 'docker.example.com'
app.config['CACHE_REDIS_PORT'] = 6379
app.config['CACHE_REDIS_DB'] = 0

cache = Cache(app)

@app.route("/Foo")
def Foo():
    time.sleep(5)
    return "Hello"

@app.route("/Bar")
@cache.cached(timeout=60)
def Bar():
    time.sleep(5)
    return "World"

if __name__ == "__main__":
    app.run()

 

Or instead of using CACHE_REDIS_HOST and CACHE_REDIS_PORT and CACHE_REDIS_DB you can instead go with CACHE_REDIS_URL with "redis://" (single trailing s) to connect to a Redis system that is NOT using SSL/TLS or with "rediss://" (two trailing s) to connect to a Redis system that is using SSL/TLS.

CACHE_REDIS_URL

from flask import Flask
import time
from flask_caching import Cache

app = Flask(__name__)

app.config['CACHE_TYPE'] = 'redis'
app.config['CACHE_REDIS_URL'] = 'redis://docker.example.com:6379'

cache = Cache(app)

@app.route("/Foo")
def Foo():
    time.sleep(5)
    return "Hello"

@app.route("/Bar")
@cache.cached(timeout=60)
def Bar():
    time.sleep(5)
    return "World"

if __name__ == "__main__":
    app.run()

 

And then run your Flask app using the Docker image and the updated main.py file.

sudo docker run \
--detach \
--name my-flask-app \
--volume /path/to/main.py:/app/main.py \
--publish 0.0.0.0:12345:80 \
myimage:latest

 

Let's clear your web browsers cache to ensure the request is not being returned from your browsers cache.

 

Just like before, each time we go to the /Foo endpoint, it will take 5 seconds for "Hello" to be returned since the /Foo endpoint is NOT being cached.

On the other hand, since the /Bar endpoint is being cached for 60 seconds, if the /Bar endpoint is not currently in Redis cache, it will take 5 seconds for "World" to be returned.

 

However, once the /Bar endpoint has been requested, there should be a key in Redis for the /Bar endpoint, which can be seen with the redis-cli --scan command.

~]$ sudo docker exec redis redis-cli --scan
flask_cache_view//Bar

 

And there should no longer be a 5 second delay to return the /Bar endpoint since the request was obtained from Redis cache. Nice!

 

Almost always, Flask apps are not a single main.py file, and instead are comprised of multiple different files. Let's say your Flask app has a structure like this.

├── main.py
├── my-project (directory)
│   ├── __init__.py
│   ├── views.py

 

main.py could have the following.

from my-project import app

app = app()

if __name__ == '__main__':
    app.run()

 

And __init__.py could have this.

from flask import Flask
from flask_caching import Cache

cache = Cache()

def app():
    app = Flask(__name__)
    
    app.config['CACHE_TYPE'] = 'redis'
    app.config['CACHE_REDIS_HOST'] = 'docker.example.com'
    app.config['CACHE_REDIS_PORT'] = 6379
    app.config['CACHE_REDIS_DB'] = 0
  
    from .views import views
    app.register_blueprint(views, url_prefix='/')

    cache.init_app(app)

    return app

 

And views.py could have this.

import requests
from flask import Blueprint, request
from . import cache

views = Blueprint('views', __name__)

@app.route("/Bar")
@cache.cached(timeout=60)
def Bar():
    time.sleep(5)
    return "World"

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 7de283 in the box below so that we can be sure you are a human.