Step 1 of 3 · Reading · ~2 min
Atomic Counters
String Commands
INCR & DECR — Atomic Counters
INCR is one of Redis's most-used commands in practice — rate limiters, view counters, unique ID generators all lean on it. The interesting part isn't the arithmetic; it's what "atomic" buys you and how you handle the type coercion between "a string in a string-only store" and "an integer you can do math on."
Values are strings; INCR interprets them as integers
Recall from the SET/GET lesson that everything in store is a string. INCR doesn't change that storage model — it reads the string, parses it as a base-10 integer, adds one, and writes the result back as a string:
INCRBY/DECRBY are the same operation parameterized by an amount instead of a fixed step of 1:
DECR/DECRBY are INCR/INCRBY with the sign flipped — implement one in terms of the other rather than duplicating logic.
Missing key defaults to 0
INCR counter on a key that has never been set should behave exactly as if counter held "0" — the result is 1, and the key now exists holding "1". This is different from an error; a missing key is a valid starting point, not a failure.
Why "atomic" is the whole point
If a client had to GET, add 1 in its own code, then SET the result, two concurrent clients could both read 5, both compute 6, and both write 6 — losing an increment. INCR avoids this entirely by doing the read-modify-write inside a single command that your single-threaded command loop executes without interruption. This is the same atomicity guarantee you relied on for SET NX — it's a recurring theme in Redis's design: push compound operations into the server so clients can't race each other.
Edge cases
- Non-integer values:
SET key hellothenINCR keymust return-ERR value is not an integer or out of range\r\n— don't let a Pythonint("hello")ValueErrorleak as an unhandled exception or a generic error message; the wording is tested precisely. - Overflow: real Redis operates on 64-bit signed integers and errors on overflow; depending on your test suite's scope, you may not need to replicate the exact 64-bit boundary, but be aware Python's arbitrary-precision integers won't naturally raise where a real Redis server would.
- Leading/trailing whitespace or a value like
"3.0": these should also fail as "not an integer" —int("3.0")already raises in Python, which is the behavior you want; don't pre-process withfloat()first.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…