How to Implement a Redis-Like Cache Dictionary in Python

Build a RedisMockDict class that mimics basic Redis key-value operations with TTL support, expiry cleanup, and standard dict-like methods.

Medium Python 3.9+ Aug 9, 2026 Caching & Redis 12 views 0 copies

Python code

80 lines
Python 3.9+
from collections import OrderedDict
import time

class RedisMockDict:
    def __init__(self, ttl=None):
        self._data = OrderedDict()
        self._ttl = ttl  # default TTL in seconds, None = no expiry
        self._expiry = {}

    def set(self, key, value, ttl=None):
        """Set a key-value pair with optional TTL."""
        self._data[key] = value
        self._expiry[key] = time.time() + (ttl if ttl is not None else self._ttl or 0)

    def get(self, key):
        """Get value; returns None if key missing or expired."""
        if key not in self._data:
            return None
        expiry = self._expiry[key]
        if expiry and time.time() > expiry:
            self.delete(key)
            return None
        return self._data[key]

    def delete(self, key):
        """Delete a key."""
        if key in self._data:
            del self._data[key]
            del self._expiry[key]

    def exists(self, key):
        """Check if key exists and is not expired."""
        return self.get(key) is not None

    def expire(self, key, seconds):
        """Set/update TTL for an existing key."""
        if key in self._data:
            self._expiry[key] = time.time() + seconds

    def ttl(self, key):
        """Remaining TTL in seconds; -1 if no expiry, -2 if key missing."""
        if key not in self._data:
            return -2
        expiry = self._expiry[key]
        if not expiry:
            return -1
        remaining = expiry - time.time()
        return max(int(remaining), 0)

    def __len__(self):
        """Number of live keys."""
        self._cleanup()
        return len(self._data)

    def _cleanup(self):
        """Remove expired keys."""
        now = time.time()
        expired = [k for k, e in self._expiry.items() if e and e <= now]
        for k in expired:
            self.delete(k)

    def __repr__(self):
        self._cleanup()
        return f"RedisMockDict({dict(self._data)})"


if __name__ == "__main__":
    cache = RedisMockDict()
    cache.set("user:1", {"name": "Alice"}, ttl=2)
    cache.set("user:2", "Bob")

    print("Get user:1:", cache.get("user:1"))
    print("TLL user:1:", cache.ttl("user:1"))
    
    time.sleep(3)
    
    print("After expiry, get user:1:", cache.get("user:1"))
    print("After expiry, exists user:1:", cache.exists("user:1"))
    print("TTL user:2:", cache.ttl("user:2"))
    print("Cache size:", len(cache))

Output

stdout
Get user:1: {'name': 'Alice'}
TLL user:1: 2
After expiry, get user:1: None
After expiry, exists user:1: False
TTL user:2: -1
Cache size: 1

How it works

The class wraps an OrderedDict to preserve insertion order and a parallel dict tracking expiry timestamps. set stores the current time plus TTL, while get lazily deletes expired keys on access. The _cleanup method scans for expired entries and removes them, keeping len and __repr__ accurate. ttl returns -2 for missing keys, -1 for no expiry, or remaining seconds as an integer. This mirrors Redis semantics while staying dependency-free with the standard library.

Common mistakes

  • Using `time.sleep` in production code — block only in tests or demos
  • Assuming `get` returns the actual value instead of None for missing/expired keys
  • Forgetting to set a default TTL, so keys never expire when `ttl=None`

Variations

  1. Use `threading.Lock` or `asyncio.Lock` to make the cache thread-safe
  2. Replace `OrderedDict` with a plain `dict` for Python 3.7+ where insertion order is guaranteed

Real-world use cases

  • Mocking Redis in unit tests without requiring a live server dependency.
  • Caching database query results in a single-process Flask/FastAPI app.
  • Storing short-lived session tokens or rate-limit counters in memory.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Caching & Redis

Related tutorials and quizzes for this topic.