Redis INCR DECR Counter Mock in Python
Simulate Redis INCR and DECR commands with a Python class to test counter logic without a live Redis server.
Python code
37 linesclass RedisCounter:
def __init__(self):
self._store = {}
def incr(self, key: str, amount: int = 1) -> int:
if key not in self._store:
self._store[key] = 0
self._store[key] += amount
return self._store[key]
def decr(self, key: str, amount: int = 1) -> int:
if key not in self._store:
self._store[key] = 0
self._store[key] -= amount
return self._store[key]
def get(self, key: str) -> int:
return self._store.get(key, 0)
def delete(self, key: str) -> bool:
if key in self._store:
del self._store[key]
return True
return False
if __name__ == "__main__":
redis_mock = RedisCounter()
print("Initial get('visits'):", redis_mock.get("visits"))
print("INCR visits:", redis_mock.incr("visits"))
print("INCR visits by 5:", redis_mock.incr("visits", 5))
print("DECR visits:", redis_mock.decr("visits"))
print("DECR likes:", redis_mock.decr("likes", 3))
print("Final get('visits'):", redis_mock.get("visits"))
print("Delete visits:", redis_mock.delete("visits"))
print("Get visits after delete:", redis_mock.get("visits"))
Output
Initial get('visits'): 0
INCR visits: 1
INCR visits by 5: 6
DECR visits: 5
DECR likes: -3
Final get('visits'): 5
Delete visits: True
Get visits after delete: 0
How it works
The mock class stores counters in a plain dictionary, mapping string keys to integer values. Atomicity is simulated by the fact that Python operations are synchronous, but real Redis guarantees atomicity at the server level. Using get with a default of 0 ensures missing keys behave like Redis counters, starting at zero. The delete method mirrors Redis's DEL command, returning True when the key existed. In production, replace this with a real Redis client to gain persistence and concurrency safety.
Common mistakes
- Assuming the mock is thread-safe; use a lock or real Redis for concurrent access.
- Forgetting to initialize a key to 0 before incrementing, though the mock handles it automatically.
- Returning None for missing counters instead of 0 as Redis does.
Variations
- Use `collections.Counter` as a base and override methods for Redis-like behavior.
- Implement a context manager to auto-close a real Redis connection after use.
Real-world use cases
- Testing rate-limiting logic that uses INCR and EXPIRE without setting up a local Redis instance.
- Developing and unit-testing analytics dashboards that track page view counts in a CI environment.
- Prototyping a leaderboard or ranking feature locally before hooking it to a managed Redis service.
Sponsored
More from Caching & Redis
- Cache Asides in Python with a Read-Through Loader easy
- Cache Data in Redis with Python easy
- Cache Penetration Null Object Mock in Python medium
- Cache Stampede Prevention with SingleFlight in Python medium
- Cache Warming with Python: Preload Hot Keys easy
- Coalescing duplicate in-flight requests: one shared result for concurrent callers hard
Keep learning
Related tutorials and quizzes for this topic.