Command Palette

Search for a command to run...

Hectal
PHASE 1Beginner ~16 min· topic 1 of 6

Topic 1.1

Strings: Values, Counters, and Conditional Writes

In one line

A Redis string is a binary-safe byte array up to 512 MB. It holds cached blobs, integers you can increment atomically, and flags you can set conditionally with an expiry, which makes it the building block for counters, locks and rate limiters.

0/6 · 0%

Think of it like this

A numbered ticket dispenser at a deli counter. Two customers can press the button at exactly the same moment and still get different numbers, because the machine hands them out one at a time. INCR is that machine: no matter how many app servers call it concurrently, every caller gets a unique, ordered number.

Key ideas

  1. 01

    Core commands: SET, GET, MSET/MGET (many keys in one round trip), INCR/INCRBY/DECR/INCRBYFLOAT, APPEND, STRLEN, GETRANGE/SETRANGE, GETDEL and GETEX (6.2). All single-key operations are O(1) except range operations, which are O(length).

  2. 02

    SET has options that replace older commands: NX (only if absent, replaces SETNX), XX (only if present), EX/PX/EXAT/PXAT (expiry), KEEPTTL (don't reset the TTL on overwrite), and GET (return the old value, replaces the deprecated GETSET). SET lock:job token NX PX 30000 is one atomic command for "create with expiry if absent", the basis of locks (Topic 12.1).

  3. 03

    Integers are stored efficiently: a string that looks like a 64-bit signed integer uses the int encoding. INCR on a missing key starts from 0. Going past the range returns ERR increment or decrement would overflow, so overflow is an error, never a silent wrap-around. Shared integer objects (0–9999) cost no extra memory.

  4. 04

    Other encodings: embstr for short strings (up to 44 bytes, stored in one allocation with the object header) and raw for longer ones. OBJECT ENCODING key shows which one you have. Values have a hard limit of 512 MB, but anything over about 100 KB is a big-key smell (Topic 13.2).

  5. 05

    Atomicity: every command is atomic, so INCR is safe from any number of clients. But a sequence like GET then SET is not atomic; another client can write between them. Use one command, SET ... NX/XX/GET, WATCH, or Lua (Phase 3) when correctness depends on the previous value.

  6. 06

    A common trap: SET key value without KEEPTTL removes any existing TTL. Code that updates a cached value and forgets the expiry turns a cache entry into a permanent key.

Code & diagrams

strings.redisredis
127.0.0.1:6379> SET product:123:views 0
OK
127.0.0.1:6379> INCR product:123:views
(integer) 1
127.0.0.1:6379> INCRBY product:123:views 10
(integer) 11
127.0.0.1:6379> SET feature:dark-mode on NX EX 60
OK
127.0.0.1:6379> SET feature:dark-mode off NX EX 60
(nil)                       # already exists, nothing written
127.0.0.1:6379> SET cfg:rate 100 EX 300
OK
127.0.0.1:6379> SET cfg:rate 200 KEEPTTL
OK
127.0.0.1:6379> TTL cfg:rate
(integer) 294               # TTL kept
127.0.0.1:6379> SET cfg:rate 300
OK
127.0.0.1:6379> TTL cfg:rate
(integer) -1                # TTL silently removed
127.0.0.1:6379> SET counter 9223372036854775807
OK
127.0.0.1:6379> INCR counter
(error) ERR increment or decrement would overflow
127.0.0.1:6379> MGET product:123:views cfg:rate missing
1) "11"
2) "300"
3) (nil)
view-counter.mermaiddiagram

Many app servers, one counter, no lost updates: INCR runs one at a time on the server.

Rendering diagram…

Interview problem

The problem

Page view counter at 1M requests/sec

Count product page views. Traffic peaks at 1 million requests per second across all products. The product page shows the view count. Start with the simple design, then handle a product going viral.

You're given

  • 1M views/sec total
  • Count shown on page
  • Approximate counts are OK on the page
  • Daily totals must be accurate for billing

The interviewer follows up

01

Why not just UPDATE products SET views = views + 1 in the database?

02

How would you count unique viewers instead of views?

When it breaks

Read-modify-write on a counter from multiple app servers

What you see

Two servers GET 41, both SET 42: one view is lost. Under load, counts drift far below reality and nobody sees an error.

Fix & prevent

Use INCR/INCRBY (atomic on the server), or Lua for more complex updates.

Cache update with plain SET removes the TTL

What you see

Keys that should expire live forever; memory creeps up until eviction or OOM errors start.

Fix & prevent

Use SET ... EX on every write or KEEPTTL when updating; audit with redis-cli --scan plus TTL sampling and alert on keys with no TTL in cache namespaces.

Explain it without notes

01

Why is INCR safe with 100 concurrent clients while GET + SET isn't?

02

What do SET options NX, XX, GET and KEEPTTL each do, and which old commands do they replace?

Practice

01

Implement a "login attempts" counter that locks an account after 5 failed attempts within 15 minutes, using only string commands.

02

Use OBJECT ENCODING on values "42", "hello" and a 100-character string. Explain each result.

Trade-offs

  • ↔

    One string holding a JSON blob vs a hash with fields: the string is simpler and you read it all at once; the hash lets you update single fields atomically and read part of the object (Topic 1.2).

  • ↔

    Exact counters on one hot key vs sharded or buffered counters: exactness and simplicity against write throughput.

Done when you can

  • I can use SET with NX, XX, EX, PX, KEEPTTL and GET correctly.

  • I can design a high-throughput counter and fix the hot-key version.

  • I know when a string is int, embstr or raw.