Intro
This guide covers the Redis commands that operators and developers reach for every day: setting keys with expirations, atomic counters, hashes for object data, lists for queues, sets for membership, sorted sets for rankings, safe iteration with SCAN, optimistic transactions, pub/sub messaging, and essential health checks. Every example uses the app:test:* namespace so you can run them against a real instance without touching production data.
Workflow Overview
Follow this sequence for reliable, repeatable results:
- Connect and sanity check —
PINGandINFOconfirm reachability and baseline metrics. - Strings and expirations —
SET/GETwithEX/TTLfor cache-like data. - Counters —
INCR/DECRwith TTL for rate limits and metrics. - Collections —
HASH,LIST,SET,ZSETcommands for structured data. - Safe iteration —
SCANinstead ofKEYSto avoid blocking. - Transactions —
WATCH,MULTI,EXECfor compare-and-swap updates. - Pub/Sub — quick fan-out messaging for ephemeral events.
- Observability —
INFO,MEMORY,SLOWLOGfor health and tuning.
Keys and Strings
Connect and ping
redis-cli PING
Expected output: PONG
Set with expiration and get
redis-cli SET app:test:greeting "hello" EX 60 NX
redis-cli GET app:test:greeting
redis-cli TTL app:test:greeting
Notes:
EXsets seconds-to-live.NXavoids overwriting existing keys; useXXto require existence.- Namespaces like
app:test:*isolate samples from real data.
Update value and check existence
redis-cli SET app:test:greeting "hello, world" XX
redis-cli EXISTS app:test:greeting
Get and change TTL in one step
redis-cli GETEX app:test:greeting EX 120
redis-cli TTL app:test:greeting
Remove expiration if needed
redis-cli PERSIST app:test:greeting
Delete carefully (target test namespaces only)
redis-cli DEL app:test:greeting
Multi-key operations
redis-cli MSET app:test:a 1 app:test:b 2
redis-cli MGET app:test:a app:test:b
Counters and Rate Limits
Initialize with TTL, then increment atomically
redis-cli SET app:test:login:count 0 EX 3600 NX
redis-cli INCR app:test:login:count
redis-cli INCRBY app:test:login:count 5
redis-cli TTL app:test:login:count
Pattern: Ensure the TTL persists for counters by setting it when the key is first created (SET ... NX EX). For sliding windows, use INCR with separate timestamped keys per window bucket (e.g., ratelimit:u123:2024011514 for 14:00 UTC).
Simple rate limit check (fixed 60-second window)
redis-cli INCR app:test:ratelimit:u123
redis-cli TTL app:test:ratelimit:u123
If TTL returns -2 (key has no expiry), apply it now for a 60-second window:
redis-cli EXPIRE app:test:ratelimit:u123 60
Then check the count against your limit (e.g., 10 requests/minute):
redis-cli GET app:test:ratelimit:u123
Hashes
Hashes store object-like fields efficiently — ideal for user profiles, session data, or product records.
redis-cli HSET app:test:user:1001 name "Ada" plan "pro" visits 1
redis-cli HGET app:test:user:1001 name
redis-cli HMGET app:test:user:1001 name plan visits
redis-cli HINCRBY app:test:user:1001 visits 1
Caution: HGETALL can be heavy on very large hashes (thousands of fields). Prefer HMGET for specific fields when possible.
Lists
Lists work well for queues and ordered logs. Use small payloads (IDs) and fetch full data from a hash or database.
FIFO queue with LPUSH + RPOP
redis-cli DEL app:test:queue:emails
redis-cli LPUSH app:test:queue:emails id-1 id-2 id-3
redis-cli RPOP app:test:queue:emails
redis-cli RPOP app:test:queue:emails
Blocking pop (waits for an item, 5-second timeout)
redis-cli BRPOP app:test:queue:emails 5
Output format: 1) "app:test:queue:emails" 2) "id-3"
Sets and Sorted Sets
Sets — unique items, ideal for membership and de-dup
redis-cli SADD app:test:room:active u1 u2 u2 u3
redis-cli SISMEMBER app:test:room:active u2
redis-cli SMEMBERS app:test:room:active
redis-cli SREM app:test:room:active u1
Sorted sets — rank items by score
redis-cli ZADD app:test:scores 100 u1 250 u2 180 u3
redis-cli ZRANGE app:test:scores 0 -1 WITHSCORES
redis-cli ZREVRANGE app:test:scores 0 1 WITHSCORES
redis-cli ZINCRBY app:test:scores 25 u1
Use case: leaderboards, priority queues, time-series ordering.
Finding Data Safely
Avoid KEYS in production — it blocks the server on large datasets. Prefer SCAN, which is incremental and non-blocking.
Basic SCAN pattern
redis-cli SCAN 0 MATCH app:test:* COUNT 100
Output: cursor followed by matching keys. Loop until the cursor returns 0 to finish scanning.
# Cursor 0 -> first batch
redis-cli SCAN 0 MATCH app:test:* COUNT 100
# Returns: 1) "17" 2) 1) "app:test:a" 2) "app:test:b" ...
# Cursor 17 -> next batch
redis-cli SCAN 17 MATCH app:test:* COUNT 100
# Returns: 1) "0" 2) 1) "app:test:user:1001" ...
Collection-specific variants
HSCAN key cursor [MATCH pattern] [COUNT n]SSCAN key cursor [MATCH pattern] [COUNT n]ZSCAN key cursor [MATCH pattern] [COUNT n]
Transactions
Use WATCH + MULTI + EXEC for optimistic locking. If another client modifies a watched key, EXEC returns nil — retry the whole flow.
Example: transfer credits if balance is sufficient
# Seed demo data
redis-cli SET app:test:balance:u1 100
redis-cli SET app:test:balance:u2 50
# Start a guarded update: debit 30 from u1, credit 30 to u2
redis-cli WATCH app:test:balance:u1
redis-cli GET app:test:balance:u1
# Returns "100" — proceed
redis-cli MULTI
redis-cli DECRBY app:test:balance:u1 30
redis-cli INCRBY app:test:balance:u2 30
redis-cli EXEC
If EXEC returns (nil), another client changed balance:u1 — re-read and retry.
Pub/Sub Basics
Publish/subscribe is for ephemeral messages (not stored). Late subscribers miss past messages.
Terminal A (subscriber)
redis-cli SUBSCRIBE app:test:events
Output:
1) "subscribe"
2) "app:test:events"
3) (integer) 1
Terminal B (publisher)
redis-cli PUBLISH app:test:events "hello subscribers"
Returns (integer) 1 — number of clients that received the message.
Terminal A receives
1) "message"
2) "app:test:events"
3) "hello subscribers"
Observability and Health
Quick checks
PING— confirms reachability.INFO— server, memory, clients, keyspace stats.
redis-cli INFO memory | head -n 10
Memory usage of a specific key
redis-cli MEMORY USAGE app:test:user:1001
Returns bytes (e.g., 112). Use MEMORY USAGE key SAMPLES 5 for large collections.
Find slow commands
redis-cli SLOWLOG GET 10
Output fields: unique ID, unix timestamp, duration in microseconds, command + args. Investigate anything over your latency budget (e.g., >10ms).
Live traffic debugging
MONITOR streams every command — use carefully and briefly.
redis-cli MONITOR
Press Ctrl-C to quit. Warning: on busy instances, MONITOR output volume can affect performance.
Local Pilot Plan
Keep the first rollout narrow, measurable, and easy to inspect.
Scope
- Namespace all test keys under
app:test:*. - Exercise only these commands:
SET/GET/EXPIRE/TTL,INCR,HSET/HGET,LPUSH/RPOP,SADD/SISMEMBER,ZADD/ZRANGE,SCAN,INFO.
Steps
- Sanity check:
PINGandINFO memory; record baselineused_memoryand keyspace stats. - Run the examples in this guide exactly as written.
- Verify outcomes:
MGETvalues,TTLs,SCANcounts, andMEMORY USAGEon a few keys. - Clean up:
DELonly keys underapp:test:*. - Compare before/after
INFO keyspaceandmemoryto ensure no strays.
Success criteria
- All commands return expected values.
- No lingering keys after cleanup (
SCAN app:test:*returns none). - No slowlog entries introduced by the pilot.
Conclusion
You now have a practical toolkit for daily Redis operations: safe key creation with expirations, atomic counters, object-like hashes, queues with lists, unique and ranked collections with sets and sorted sets, non-blocking iteration via SCAN, simple optimistic transactions, pub/sub for ephemeral events, and essential health checks via INFO, MEMORY, and SLOWLOG. Keep examples namespaced, favor SCAN over KEYS, and monitor INFO, MEMORY, and SLOWLOG during experiments. Start with the local pilot, confirm results, then expand to your application-specific keys and patterns.