DEV Community

Bernice Waweru
Bernice Waweru

Posted on • Edited on

Caching in Python

caching is winning the battle without the fight.

Caching refers to storing data in a cache for faster retrieval. Caching facilitates easier scaling by enabling you to return responses without computing them all the time.

A cache is a piece of hardware or software that stores data allowing future responses to be served faster decreasing time taken to return responses.

Caching is used in different systems including the central processing unit (CPU) memory caches, hard drive caches, Linux operating system file caches, database query caches, Domain Name System (DNS) client caches, Hypertext Transfer Protocol (HTTP) browser caches, HTTP proxies and reverse proxies.

It is important to consider when and where to caching to leverage its ability to improve application performance.

Cache Hit Ratio
The Cache hit ratio is measure of how many times you can reuse the same cached response.
For instance, a 90% cache hit ratio with ten requests means that you hit the cache 9 out of 10 times. You only compute the response once and serve the same response for the other nine requests.

A high cache hit ratio is desirable although one must ensure the response does not become stale.

Factors affecting cache hit ratio

Data Size

The number of all possible cache keys an application can generate affects the cache hit ratio because the more unique the cache keys the lower the cache hit ratio.

Space

The size of the objects and the size of the cache determine the cache hit ratio because objects have to be evicted to fit the cache.
The more responses that can fit in the cache the higher the cache hit ratio.

Longevity

The average time a response can be stored in cache before expiring or being invalidated determines the cache hit ratio.

A Time to Live(TTL) is defined indicating the time an object can stay in the cache before expiring.
The longer the TTL the higher the cache hit ratio.

Ideal Cases for Caching

Use cases with a high ratio of reads to writes; the cached objects can be created once and stored for longer periods of time before becoming invalid.

Unideal Cases for Caching

Use cases with data updating very often may render cache useless, as objects in cache may become invalid before they are used again.

Implementation in Redis

In this post we will explore how to implement caching using Redis.

Redis is a one of the most popular data stores used as a cache together with Python due to its capabilities.

To get started with Redis, install redis using

pip install redis

On the command line, run redis-cli to connect to redis.
Data in redis is stored as key-value pairs where the keys have to be unique.

You can think of redis as a glorified dictionary.

Useful Commands

To store data use the SET command.
Syntax: set key value
The SET command has several options that specify how the data should be stored.

Use the GET command to retrieve data using the key.
Syntax: get key

Use keys * to retrieve all the keys of the stored data.

Redis

connect Python Client to Redis

Let us see how to use Redis to cache data retrieved from an API

Create a file caching.py

import redis
import sys

def connect_redis():
try:
        client = redis.Redis(
            host="localhost",
            port=6379,
            db=0,
            socket_timeout=5,
        )
        ping = client.ping()
        if ping is True:
            print("Connection Established!")
            return client
    except redis.AuthenticationError:
        print("AuthenticationError")
        sys.exit(1)

client = connect_redis()

Enter fullscreen mode Exit fullscreen mode

connect_redis() tries to connect to the redis server.

Getting data from the jsonplaceholder API and storing it in redis.

def get_data_from_api(url):
    data = requests.get(url).json()
    return data

def set_data_to_cache(data):
    id = data['id']
    title = data['title']
    timeout = 30
    return client.setex(id,title,timeout)

Enter fullscreen mode Exit fullscreen mode

Get data from cache and display it

def get_data_from_cache(id):
    title = client.get(id)
    return title

def display_data(id):
    title = get_data_from_cache(id)
    if title is not None:
        return title
    else:
        data = get_data_from_api(url)
        print(data['title'])
        title = data['title']
        return title

client = redis_connect()
url = "https://jsonplaceholder.typicode.com/posts/1"
display_data("1")

Enter fullscreen mode Exit fullscreen mode

You can find the code here
Happy Learning !!!

References

Web Scalability for Startup Engineers.

Top comments (0)