DevTools

Cheatsheet Redis

Base de dados em memória (chave-valor)

Back to languages
Redis
64 cards found
Categories:
Versions:

Basic Commands


8 cards
Connection (redis-cli)
redis-cli                    # connect locally (6379)
redis-cli -h 192.168.1.10   # remote host
redis-cli -p 6380           # custom port
redis-cli -a my_password    # with password
redis-cli -n 2              # database 2
redis-cli --tls             # with TLS

redis-cli is the command-line client. -h sets the host, -p the port, -a the password. -n selects the database (0-15 by default).

Select database
SELECT 0        # database 0 (default)
SELECT 1        # database 1
DBSIZE          # number of keys in the current DB
MOVE key 1      # move key to DB 1
FLUSHDB         # clear the current DB (CAREFUL!)

Redis has 16 logical databases (0-15) by default. SELECT switches between them. They are isolated but share memory. In production, prefer separate instances or namespaces with prefixes.

First commands
PING              # replies PONG
SET name "Anna"   # store a value
GET name          # read → "Anna"
DEL name          # delete key
EXISTS name       # key exists? (1/0)
TYPE name         # value type

PING tests the connection. SET stores, GET reads, DEL deletes. EXISTS checks presence. TYPE returns the type: string, list, hash, set, zset.

SCAN (safe iteration)
SCAN 0 MATCH user:* COUNT 100
# → [cursor, [keys...]]

SCAN 17 MATCH user:* COUNT 100
# continues from cursor 17

# Cursor 0 = finished
# HSCAN, SSCAN, ZSCAN for composite types

SCAN iterates keys without blocking the server. It returns a cursor and a batch. Repeat until cursor = 0. HSCAN for hashes, SSCAN for sets, ZSCAN for sorted sets.

Manage keys
KEYS user:*        # keys matching a pattern
SCAN 0 MATCH user:* COUNT 100  # iterative (safe)
TYPE key           # value type
RENAME old new     # rename key
RANDOMKEY          # random key
OBJECT ENCODING key  # internal representation

KEYS returns all keys matching the pattern — it blocks in production! Use SCAN the an iterative and safe alternative. OBJECT ENCODING shows the internal structure.

DEL and UNLINK
DEL key1 key2 key3   # synchronous (blocks)
UNLINK key1 key2     # asynchronous (background)

# UNLINK frees memory in a separate thread
# Ideal for large keys (lists, hashes)
# Returns the number of keys removed

DEL removes synchronously — it can block with large keys. UNLINK (Redis 4+) removes in the background without blocking. Prefer UNLINK in production for keys with many elements.

Data types
string   # text or number (SET/GET)
list     # ordered list (LPUSH/RPUSH)
hash     # object with fields (HSET/HGET)
set      # unique set (SADD)
zset     # set ordered by score (ZADD)
stream   # event stream (XADD)
bitmap   # individual bits (SETBIT)
hyperloglog  # approximate count (PFADD)

Redis has 8 data types. string is the most versatile. hash models objects. zset is ideal for rankings. stream for persistent queues. Each type has specific commands.

COPY and OBJECT
COPY source dest             # copy key
COPY source dest DB 1        # copy to another DB
COPY source dest REPLACE     # overwrite destination

OBJECT ENCODING key   # int, embstr, raw, listpack...
OBJECT IDLETIME key   # seconds without access
OBJECT FREQ key       # frequency (LFU)

COPY (Redis 6.2+) duplicates a key. OBJECT ENCODING shows the internal representation. IDLETIME indicates how long since it was accessed. Useful for debugging and optimization.

Strings


8 cards
SET and GET
SET city "Lisbon"
GET city                # "Lisbon"

# SET options:
SET token "abc" EX 60   # expires in 60s
SET key "v" NX          # only if it does NOT exist
SET key "v" XX          # only if it exists
SET key "v" KEEPTTL     # keep the existing TTL

SET stores a value. GET reads it. Options: EX (seconds), PX (ms), NX (create only), XX (update only), KEEPTTL preserves expiration.

SET with expiration
SET session "xyz" EX 3600     # 1 hour
SET temp "v" PX 5000          # 5000 milliseconds
SET lock "1" NX EX 10         # 10s lock (only if it does not exist)
SET cache "html" EXAT 1700000000  # Unix timestamp

# EX = seconds, PX = milliseconds
# EXAT = absolute timestamp, PXAT = absolute ms

Combines SET with a TTL in one atomic operation. NX EX is the pattern for distributed locks. EXAT sets expiration by an absolute timestamp. Avoids race conditions vs separate SET + EXPIRE.

Counters (INCR/DECR)
SET visits 10
INCR visits         # 11
INCRBY visits 5     # 16
DECR visits         # 15
DECRBY visits 3     # 12
INCRBYFLOAT price 1.5  # decimal add

# If the key does not exist, it starts at 0
INCR new_key        # 1

INCR/DECR are atomic operations — safe under concurrency. Ideal for counters, rate limiting and sequential IDs. INCRBY adds N. INCRBYFLOAT for decimals.

Bitmaps
SETBIT presence 0 1    # bit 0 = 1
SETBIT presence 1 0    # bit 1 = 0
GETBIT presence 0      # 1
BITCOUNT presence      # total of bits set to 1
BITPOS presence 1      # position of the first 1
BITOP AND result set1 set2  # operation between bitmaps

Bitmaps operate at the bit level over strings. Ultra-compact for flags (presence, daily login). BITCOUNT counts active bits. 1 MB stores ~8 million flags. Ideal for analytics.

MSET and MGET (batch)
MSET a "1" b "2" c "3"    # store several
MGET a b c                 # ["1", "2", "3"]

MSETNX a "1" b "2"        # only if NONE exists

# MGET returns nil for missing keys
MGET a missing c          # ["1", nil, "3"]

MSET/MGET operate on multiple keys in one call — reduces round-trips. MSETNX is atomic: it only sets if no key exists. More efficient than individual SET/GET.

HyperLogLog
PFADD visits "user1" "user2" "user3"
PFADD visits "user2" "user4"
PFCOUNT visits          # 4 (approximate uniques)

PFMERGE total set1 set2  # merge counts

# Standard error: ~0.81%
# Uses only 12 KB of memory (vs millions in a SET)

HyperLogLog counts unique elements with minimal memory (12 KB). Error ~0.81%. Ideal for counting unique visitors, UVs. PFADD adds, PFCOUNT estimates, PFMERGE merges.

Manipulate strings
APPEND name " Silva"     # append to the end
STRLEN name              # length
SETRANGE name 0 "X"      # replace a position
GETRANGE name 0 3        # substring
GETDEL name              # read and delete (6.2+)
GETSET name "new"        # swap and return the old

APPEND concatenates. STRLEN gives the length. GETRANGE extracts a substring. GETDEL (6.2+) reads and removes atomically. Strings up to 512 MB maximum size.

GETEX and GETDEL
# Read and set TTL atomically (6.2+)
GETEX key EX 60      # read + expire in 60s
GETEX key PERSIST    # read + remove TTL

# Read and delete atomically (6.2+)
GETDEL key           # returns the value and removes it

# Useful for one-time tokens:
SET otp "1234" EX 300
GETDEL otp             # use once and delete

GETEX (6.2+) reads and adjusts the TTL in one operation. GETDEL reads and removes atomically — ideal for single-use tokens. Avoids race conditions between separate GET and DEL/EXPIRE.

Lists


8 cards
Add elements
LPUSH queue "a"         # start (left)
RPUSH queue "b"         # end (right)
LPUSH queue a b c       # several at once
LINSERT queue BEFORE "b" "x"  # insert before

LLEN queue              # length
LINDEX queue 0          # element by index

LPUSH inserts on the left, RPUSH on the right. LINSERT inserts before/after a value. LLEN gives the length. Lists keep insertion order and allow duplicates.

Blocking pop (BLPOP/BRPOP)
# Waits until there is an element or a timeout
BLPOP queue 30       # 30s timeout
BRPOP queue 0        # infinite wait

# Multiple queues (priority):
BLPOP high medium low 30
# checks "high" first

# Returns nil if the timeout expires

BLPOP/BRPOP block until there is data. Ideal for workers waiting for tasks. Timeout 0 = infinite wait. Multiple lists = priority (the first with data is consumed).

Read elements
LRANGE queue 0 -1     # all elements
LRANGE queue 0 9      # first 10
LRANGE queue -5 -1    # last 5

LPOP queue            # remove and return from the start
RPOP queue            # remove and return from the end
LPOP queue 3          # remove 3 from the start (6.2+)
LMPOP 2 queue1 queue2 LEFT  # pop from multiple lists

LRANGE reads without removing (0 = first, -1 = last). LPOP/RPOP remove and return. Since 6.2+, LPOP N removes multiple. LMPOP operates on several lists.

LSET and LREM
# Update by index
LSET queue 0 "new_value"

# Remove by value
LREM queue 2 "element"    # removes 2 occurrences
LREM queue 0 "element"    # removes ALL
LREM queue -1 "element"   # removes 1 from the end

# Trim (keep only N elements)
LTRIM queue 0 99           # keep the first 100

LSET updates by index. LREM removes by value (positive count = from the start, negative = from the end, 0 = all). LTRIM truncates the list — useful to limit its size.

Queue (FIFO)
# Producer: add to the end
RPUSH tasks "job1"
RPUSH tasks "job2"
RPUSH tasks "job3"

# Consumer: remove from the start
LPOP tasks    # "job1" (first in)
LPOP tasks    # "job2"

# RPUSH + LPOP = FIFO (First In, First Out)

FIFO pattern: RPUSH to produce, LPOP to consume. The first in is the first out. Basis for message queues and simple task queues.

RPOPLPUSH (move between lists)
# Move an element from one list to another
RPOPLPUSH source dest

# Use case: processing queue
RPUSH tasks "job1"
RPOPLPUSH tasks in_progress
# ... process ...
LREM in_progress 1 "job1"

# LMOVE (6.2+, more flexible):
LMOVE source dest RIGHT LEFT

RPOPLPUSH atomically moves from the end of one list to the start of another. Reliable queue pattern: an item stays in "processing" until confirmation. LMOVE (6.2+) lets you choose the sides.

Stack (LIFO)
# Push: add to the start
LPUSH stack "a"
LPUSH stack "b"
LPUSH stack "c"

# Pop: remove from the start
LPOP stack    # "c" (last in)
LPOP stack    # "b"

# LPUSH + LPOP = LIFO (Last In, First Out)

LIFO pattern: LPUSH + LPOP (same side). The last in is the first out. Useful for stacks, undo/redo, browsing history.

List the a circular log
# Keep only the last 1000 events
RPUSH log:event "error: timeout"
LTRIM log:event -1000 -1

# Read the last 10
LRANGE log:event -10 -1

# Pattern: RPUSH + LTRIM = fixed size
# Never grows beyond the limit

Combine RPUSH + LTRIM for a fixed-size log. LTRIM -N -1 keeps only the last N. Memory efficient. Ideal for activity feeds, recent logs and limited history.

Hashes


8 cards
Create hash (HSET)
HSET user:1 name "Anna" age 30 city "Porto"

# Or field by field:
HSET user:1 name "Anna"
HSET user:1 age 30

# Only if it does not exist:
HSETNX user:1 email "anna@mail.com"

HGET user:1 name    # "Anna"

HSET sets fields in a hash. It accepts multiple field-value pairs. HSETNX only sets if the field does not exist. HGET reads a field. Ideal for modeling objects.

HSCAN (iterate a large hash)
HSCAN user:1 0 MATCH name* COUNT 100
# → [cursor, [field, value, ...]]

# Iterate all fields:
HSCAN user:1 0 COUNT 1000
# repeat with the returned cursor until 0

# Essential for hashes with thousands of fields

HSCAN iterates the fields of a hash without blocking. Essential for large hashes (thousands of fields). Returns cursor + batch. Repeat until cursor = 0. Never use HGETALL on huge hashes.

Read hash
HGETALL user:1       # all fields and values
HGET user:1 name     # one field
HMGET user:1 name age city  # several fields
HKEYS user:1         # field names
HVALS user:1         # values only
HLEN user:1          # number of fields
HSTRLEN user:1 name  # length of the value

HGETALL returns everything (careful with large hashes). HMGET specific fields. HKEYS/HVALS separate names and values. HLEN counts fields.

HRANDFIELD (6.2+)
# Random field
HRANDFIELD user:1

# 3 random fields (no repetition)
HRANDFIELD user:1 3

# With values:
HRANDFIELD user:1 3 WITHVALUES

# With repetition (negative count):
HRANDFIELD user:1 -5

HRANDFIELD (6.2+) returns random fields. Positive count = no repetition, negative = with repetition. WITHVALUES includes the values. Useful for draws and samples.

Update and delete fields
HSET user:1 age 31            # update
HINCRBY user:1 age 1          # increment (32)
HINCRBYFLOAT user:1 balance 9.5 # decimal
HDEL user:1 city              # remove field
HEXISTS user:1 name           # field exists? (1/0)
HDEL user:1 field1 field2     # remove several

HSET overwrites the field. HINCRBY increments atomically. HDEL removes fields. HEXISTS checks presence. Operations on individual fields are efficient.

Hash vs String (when to use)
# Hash: object with multiple fields
HSET user:1 name "Anna" age 30 email "a@b.com"
# → partial update: HSET user:1 age 31

# Strings: simple or serialized values
SET user:1:name "Anna"
SET user:1:json '{"name":"Anna","age":30}'
# → full update: rewrite the entire JSON

Use a hash for objects with frequent partial updates. Use a string for simple values or data always read/written together. A hash saves memory with many small fields.

Hash the an object (modeling)
# Model a product
HSET product:100 name "4K TV" price 500 stock 10 active 1

# Typical operations:
HGETALL product:100
HINCRBY product:100 stock -1    # sell
HSET product:100 active 0       # deactivate
HMGET product:100 name price    # specific fields

Hashes are perfect for modeling objects: each field is a property. Convention: type:id the the key. More efficient than multiple strings. Supports partial updates without rewriting everything.

Hash with TTL (7.4+)
# TTL per field (Redis 7.4+)
HSET session:abc user "anna" EX 3600
HSET session:abc token "xyz" EX 600

HEXPIRE session:abc 300 FIELDS user token
HTTL session:abc FIELDS user
HPERSIST session:abc FIELDS token

# Before 7.4: TTL only on the whole key
EXPIRE session:abc 3600

Since Redis 7.4+, hash fields can have an individual TTL with HSET ... EX and HEXPIRE. Before, only the whole key expired. Useful for sessions with fields of different validity.

Sets e Sorted Sets


8 cards
Sets (unique sets)
SADD tags "php" "redis" "docker"
SMEMBERS tags          # all members
SISMEMBER tags "php"   # belongs? (1/0)
SMISMEMBER tags "php" "go"  # multiple (6.2+)
SCARD tags             # number of members
SREM tags "php"        # remove member

SADD adds (ignores duplicates). SMEMBERS lists everything. SISMEMBER checks membership in O(1). SCARD counts. Sets have no order and do not allow repeats.

Rankings and leaderboards
ZREVRANGE ranking 0 2 WITHSCORES  # top 3 (desc)
ZRANK ranking "anna"              # position (asc, 0-based)
ZREVRANK ranking "anna"           # position (desc)
ZINCRBY ranking 5 "anna"          # +5 points
ZCOUNT ranking 90 100             # how many between 90-100
ZREMRANGEBYRANK ranking 0 9       # remove bottom 10

ZREVRANGE = top N (highest score first). ZRANK/ZREVRANK give the position. ZINCRBY increments the score. A perfect pattern for real-time leaderboards.

Operations between sets
SINTER a b          # intersection (common elements)
SUNION a b          # union (all without duplicates)
SDIFF a b           # difference (in a but not in b)

# Store the result:
SINTERSTORE result a b
SUNIONSTORE result a b

# Cardinality of the intersection (without storing):
SINTERCARD 2 a b LIMIT 10

SINTER = common elements. SUNION = all combined. SDIFF = only in the first. The *STORE versions store the result. SINTERCARD (7+) counts without materializing.

Ranges by score
ZRANGEBYSCORE ranking 80 100         # scores 80-100
ZRANGEBYSCORE ranking (80 100        # exclusive: >80
ZREVRANGEBYSCORE ranking 100 80      # descending
ZREMRANGEBYSCORE ranking 0 50        # remove ≤50
ZRANGEBYSCORE ranking -inf +inf      # all

# With pagination:
ZRANGEBYSCORE ranking 0 100 LIMIT 0 10

ZRANGEBYSCORE filters by score range. ( makes it exclusive. -inf/+inf for open bounds. LIMIT offset count paginates. Useful for filters by price, time, priority.

SPOP and SRANDMEMBER
SPOP draw               # remove and return a random one
SPOP draw 3             # remove 3 random ones
SRANDMEMBER draw        # view random (without removing)
SRANDMEMBER draw 5      # 5 random (without removing)

# SMOVE: move between sets
SMOVE source dest "element"

SPOP removes randomly (draws, lotteries). SRANDMEMBER views without removing (samples). SMOVE transfers between sets atomically. All O(1) or O(N) depending on the count.

ZRANGEBYLEX (lexicographic)
# All with the same score → alphabetical ordering
ZADD names 0 "anna" 0 "bruno" 0 "carla" 0 "david"

ZRANGEBYLEX names [anna [carla     # anna to carla
ZRANGEBYLEX names (anna +          # after "anna"
ZREMRANGEBYLEX names [a [b        # remove a-b
ZLEXCOUNT names [a [z             # count in the range

When all scores are equal, ZRANGEBYLEX orders lexicographically. [ = inclusive, ( = exclusive. Useful for autocomplete and ordered dictionaries.

Sorted Sets (ZADD)
ZADD ranking 100 "anna" 85 "john" 92 "maria"

ZRANGE ranking 0 -1 WITHSCORES   # all with scores
ZSCORE ranking "anna"            # 100
ZCARD ranking                    # number of members
ZMSCORE ranking "anna" "john"     # multiple scores
ZADD ranking 95 "anna"           # update score

ZADD adds with a score (or updates). ZRANGE lists ordered by score. ZSCORE queries an individual score. Sorted sets keep automatic ordering — ideal for rankings.

ZUNIONSTORE and ZDIFF
# Union of sorted sets (adds scores):
ZUNIONSTORE result 2 set1 set2
ZUNIONSTORE result 2 set1 set2 WEIGHTS 2 1

# Intersection:
ZINTERSTORE result 2 set1 set2 AGGREGATE MAX

# Difference (7+):
ZDIFF 2 set1 set2
ZDIFFSTORE result 2 set1 set2

ZUNIONSTORE unites by adding scores. WEIGHTS multiplies scores per set. AGGREGATE defines how to combine (SUM, MIN, MAX). ZDIFF (7+) shows elements only in the first.

Expiration and TTL


8 cards
Set expiration
EXPIRE key 60           # expires in 60 seconds
PEXPIRE key 5000        # in 5000 milliseconds
EXPIREAT key 1700000000 # Unix timestamp
PEXPIREAT key 1700000000000  # ms timestamp

# On creation:
SET token "abc" EX 3600   # 1 hour

EXPIRE sets a TTL in seconds. PEXPIRE in milliseconds. EXPIREAT/PEXPIREAT use an absolute timestamp. Redis removes the key automatically when it expires.

User sessions
# Create session
SET session:abc123 '{"user":"anna","role":"admin"}' EX 1800

# Renew session (on each request)
EXPIRE session:abc123 1800

# Check session
GET session:abc123    # nil = expired

# End session
DEL session:abc123

Sessions in Redis: SET with EX 1800 (30 min). EXPIRE renews on each request (sliding expiration). GET nil = expired session. Much faster than a relational DB.

Query TTL
TTL key       # seconds remaining
PTTL key      # milliseconds remaining

# Special returns:
# -2 = the key does not exist
# -1 = the key exists but has no expiration (permanent)
# >0 = seconds remaining

TTL returns the seconds until expiration. PTTL in milliseconds (more precise). -2 = does not exist, -1 = permanent. Essential for checking the state of cache and sessions.

Rate limiting
# Limit: 100 requests/min per IP
INCR rate:192.168.1.1
EXPIRE rate:192.168.1.1 60    # only on the first time

# Check:
GET rate:192.168.1.1         # > 100 → block

# Alternative with SET NX:
SET rate:ip 1 NX EX 60       # fixed window

INCR + EXPIRE implements fixed-window rate limiting. Each IP has a counter that expires in 60s. If the counter > limit, reject. Atomic and efficient. An essential pattern in APIs.

Remove expiration
PERSIST key      # make permanent (removes TTL)

# Check the state:
TTL key          # -1 = permanent

# Expire immediately:
EXPIRE key 0     # or DEL key

# GETEX (6.2+): read and adjust TTL
GETEX key PERSIST   # read + make permanent

PERSIST removes the TTL, making the key permanent. EXPIRE 0 expires immediately. GETEX PERSIST (6.2+) does read + persistence atomically.

Distributed lock
# Acquire lock (only if it does not exist, expires in 10s)
SET lock:resource "my_id" NX EX 10

# Check if it is still mine:
GET lock:resource    # "my_id"?

# Release (with Lua for atomicity):
EVAL "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock:resource my_id

SET NX EX creates a distributed lock. NX guarantees exclusivity, EX avoids a deadlock if the process dies. Release with a Lua script to check ownership. The basis of the Redlock somethingrithm.

Cache with TTL
# Cache-aside pattern:
SET cache:home "<html>..." EX 300    # 5 min
GET cache:home                        # hit?
# If nil → recalculate and SET again

# Invalidate:
DEL cache:home

# Variable TTL by type:
SET cache:profile "..." EX 600       # 10 min
SET cache:feed "..." EX 60           # 1 min

Cache-aside pattern: check the cache, on a miss recalculate and store with a TTL. EX sets the validity. DEL invalidates manually. Different TTLs per data type according to the freshness needed.

Keyspace notifications
# Enable expiration notifications:
CONFIG SET notify-keyspace-events Ex

# Subscribe to expiration events:
PSUBSCRIBE __keyevent@0__:expired

# When a key expires, you receive:
# message: "key_name"

# Useful for: expired sessions,
# reminders, scheduling

Keyspace notifications emit events when keys expire or are modified. Enable with CONFIG SET notify-keyspace-events. PSUBSCRIBE listens to events. Useful for triggers and scheduling.

Server and Admin


8 cards
INFO (information)
INFO                  # complete information
INFO memory           # memory usage
INFO clients          # connected clients
INFO stats            # operation statistics
INFO persistence      # RDB/AOF state
INFO replication      # replication state
DBSIZE                # number of keys in the current DB

INFO returns server metrics by section. memory shows the RAM used. stats shows ops/sec, hits, misses. DBSIZE counts keys. Essential for monitoring.

Eviction policies
CONFIG SET maxmemory 512mb
CONFIG SET maxmemory-policy allkeys-lru

# Available policies:
# noeviction    → error when full (default)
# allkeys-lru   → removes the least used (recommended)
# allkeys-lfu   → removes the least frequent
# volatile-lru  → LRU only with TTL
# volatile-ttl  → lowest TTL first
# allkeys-random → random

When maxmemory is reached, the policy decides what to remove. allkeys-lru is the most used for cache. volatile-lru only removes keys with a TTL. noeviction returns an error.

Clear data
DEL key               # delete one key (synchronous)
UNLINK key            # delete asynchronous (4+)
FLUSHDB               # clear the current DB
FLUSHDB ASYNC         # clear in the background
FLUSHALL              # clear ALL DBs
FLUSHALL ASYNC        # all in the background

# ⚠️ NEVER FLUSHALL in production!

DEL is synchronous (blocks). UNLINK is asynchronous (prefer it in production). FLUSHDB ASYNC clears without blocking. FLUSHALL deletes everything — extremely dangerous in production.

MONITOR and SLOWLOG
MONITOR                    # see ALL commands in real time
# ⚠️ Performance impact! Only for debugging.

SLOWLOG GET 10             # last 10 slow commands
SLOWLOG LEN                # how many recorded
SLOWLOG RESET              # clear the log

CONFIG SET slowlog-log-slower-than 10000  # >10ms

MONITOR shows all commands — heavy, only for one-off debugging. SLOWLOG records commands above the threshold. slowlog-log-slower-than in microseconds. Essential for finding bottlenecks.

Persistence (RDB and AOF)
SAVE              # synchronous snapshot (blocks!)
BGSAVE            # snapshot in the background
LASTSAVE          # timestamp of the last save

# RDB: point-in-time snapshot (dump.rdb)
# AOF: log of all writes (appendonly.aof)

# AOF config:
CONFIG SET appendonly yes
CONFIG SET appendfsync everysec

RDB = periodic snapshots (fast, loses data between saves). AOF = operation log (durable, larger file). appendfsync everysec is the ideal trade-off. Use both in production.

MEMORY (memory analysis)
MEMORY USAGE key            # bytes of a key
MEMORY USAGE key SAMPLES 0  # exact (slower)
MEMORY DOCTOR               # diagnostics
MEMORY STATS                # breakdown by category
MEMORY MALLOC-STATS         # allocator stats

INFO memory                 # general summary

MEMORY USAGE shows the exact bytes of a key. MEMORY DOCTOR gives recommendations. MEMORY STATS shows overhead, fragmentation. Useful for optimizing RAM usage.

CONFIG (configuration)
CONFIG GET maxmemory          # view a setting
CONFIG SET maxmemory 256mb    # change at runtime
CONFIG GET save               # snapshot rules
CONFIG SET maxmemory-policy allkeys-lru
CONFIG REWRITE                # persist config to file

# Without CONFIG REWRITE, it changes only in memory

CONFIG GET/SET adjusts parameters at runtime. maxmemory limits RAM. maxmemory-policy defines eviction (LRU, LFU, random). CONFIG REWRITE persists to redis.conf.

CLIENT (connection management)
CLIENT LIST                 # all active connections
CLIENT LIST TYPE normal     # only normal clients
CLIENT GETNAME              # name of this connection
CLIENT SETNAME my-worker    # give a name
CLIENT KILL ID 42           # end a connection
CLIENT PAUSE 5000           # pause clients for 5s
CLIENT NO-EVICT ON          # protect from eviction

CLIENT LIST shows connections with IP, age, last command. CLIENT KILL ends problematic connections. CLIENT SETNAME eases identification. PAUSE for maintenance.

Pub/Sub, Streams e Truques


8 cards
Pub/Sub
# Subscriber (waits):
SUBSCRIBE channel:news
PSUBSCRIBE channel:*          # pattern

# Publisher:
PUBLISH channel:news "Breaking: Redis 8 released!"

# Messages are NOT persistent
# If the subscriber is offline, it loses the message

PUB/SUB is fire-and-forget — messages are not stored. SUBSCRIBE listens, PUBLISH sends. PSUBSCRIBE accepts patterns. For persistent messages, use Streams.

Lua scripting (EVAL)
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 my_key my_value

# Script with logic:
EVAL "
  local val = redis.call('GET', KEYS[1])
  if tonumber(val) > tonumber(ARGV[1]) then
    return redis.call('DECR', KEYS[1])
  end
  return 0
" 1 counter 5

EVALSHA sha1_hash 1 key arg   # cached script

EVAL runs Lua scripts on the server — atomic and without round-trips. KEYS[] are keys, ARGV[] arguments. EVALSHA reuses cached scripts. Ideal for complex atomic logic.

Streams (XADD/XREAD)
# Add an event (automatic ID):
XADD events * type "login" user "anna"

# Read all:
XRANGE events - +
XLEN events

# Read new (from the last):
XREAD STREAMS events $

# With a consumer group:
XREADGROUP GROUP workers consumer1 STREAMS events >

Streams (Redis 5+) are persistent queues with consumer groups. XADD adds, XREAD reads. XREADGROUP allows multiple consumers. A replacement for Kafka in simple cases.

Naming conventions
# Pattern: object:field or type:id
user:1:name
user:1:sessions
product:100:stock
cache:home:v2
rate:192.168.1.1
lock:order:42

# Separator: colon (:)
# Prefixes to organize by domain

Convention: type:id:field with the : separator. Eases organization and SCAN by pattern. Prefixes like cache:, rate:, lock: identify the purpose. Avoid very long keys.

Transactions (MULTI/EXEC)
MULTI             # start transaction
SET a "1"         # queued
SET b "2"         # queued
INCR counter      # queued
EXEC              # execute everything atomically

DISCARD           # cancel (before EXEC)

# WATCH for optimistic locking:
WATCH key
MULTI
SET key "new"
EXEC              # fails if the key changed

MULTI/EXEC groups commands atomically — all or none. DISCARD cancels. WATCH implements optimistic locking: EXEC fails if the key was modified by another client.

Performance best practices
# ✅ DO:
# • SCAN instead of KEYS *
# • UNLINK instead of DEL (large keys)
# • Pipelines for batch operations
# • TTL on all cache keys
# • maxmemory + eviction policy

# ❌ AVOID:
# • KEYS * in production (blocks!)
# • Values > 10 KB with no need
# • FLUSHALL/FLUSHDB without ASYNC
# • MONITOR for a prolonged time

Use SCAN (not KEYS), UNLINK (not DEL), pipelines for batches. Always set maxmemory and an eviction policy. TTL on cache. Avoid huge values and blocking commands.

Pipelines
# Pipeline: send N commands without waiting for a response
# Drastically reduces network round-trips

# Via redis-cli:
redis-cli --pipe < commands.txt

# In code (Python example):
pipe = r.pipeline()
pipe.set("a", "1")
pipe.set("b", "2")
pipe.incr("counter")
pipe.execute()    # 1 round-trip instead of 3

Pipeline sends multiple commands in a batch without waiting for each response. It reduces network latency from N round-trips to 1. It is not atomic (unlike MULTI). 10-100x faster in batches.

Redis vs Memcached
# Redis:
# • Rich types (hash, list, set, zset, stream)
# • Persistence (RDB + AOF)
# • Pub/Sub, Streams, Lua scripting
# • Master-replica replication
# • Native cluster

# Memcached:
# • Strings only (simple key-value)
# • No persistence
# • Multi-threaded (better on multi-core)
# • Simpler, fewer features

Redis is more versatile: rich data types, persistence, scripting. Memcached is simpler and multi-threaded. For simple cache with extreme throughput, Memcached. For everything else, Redis.