Redis Deep Dive
Architecture Overview
Section titled “Architecture Overview”Redis is a single-threaded, event-driven, in-memory data structure store. It uses I/O multiplexing (epoll/kqueue/kqueue) to handle thousands of concurrent connections on a single thread.
Single-Threaded Event Loop
Section titled “Single-Threaded Event Loop”Main Thread Event Loop: 1. Accept new connections (accept()) 2. Read commands from client sockets (read()) 3. Parse and execute commands 4. Write responses to client sockets (write()) 5. Handle background tasks (fsync, AOF rewrite, etc.)Despite being single-threaded for command execution, Redis uses background I/O threads (Redis 6+) for:
- File descriptor read/write
- Lazy freeing of large keys (
UNLINKinstead ofDEL)
io-threads 4io-threads-do-reads yesMemory Model
Section titled “Memory Model”Redis stores all data in RAM. The maximum memory is controlled by maxmemory:
maxmemory 4gbmaxmemory-policy allkeys-lruData Structures
Section titled “Data Structures”Strings
Section titled “Strings”Strings are the most fundamental Redis type. They can hold text, binary data (up to 512MB), and Integers (which support atomic increment/decrement):
SET user:1001:name "Alice"GET user:1001:name# "Alice"
SET counter 100INCR counter# 101INCRBY counter 10# 111DECR counter# 110
SETEX session:abc123 3600 "user_data"# Expires in 3600 seconds
MGET user:1001:name user:1002:name user:1003:name# Bulk retrieval of multiple keysLists are linked lists (implemented as quicklists — a doubly-linked list of ziplists). They support Pushing/popping from both ends:
LPUSH queue:tasks "task1" "task2" "task3"RPOP queue:tasks# "task1"
# Blocking pop (waits until an element is available)BLPOP queue:tasks 30# Blocks for up to 30 seconds
# Range operationsLRANGE queue:tasks 0 -1# All elementsLTRIM queue:tasks 0 99# Keep only first 100 elementsUnordered collections of unique strings:
SADD tags:post:42 "redis" "database" "cache" "performance"SMEMBERS tags:post:42# "redis" "database" "cache" "performance"
SISMEMBER tags:post:42 "redis"# 1 (true)
# Set operationsSINTER tags:post:42 tags:post:43# Common tags between two postsSUNION tags:post:42 tags:post:43# All tags across both postsSDIFF tags:post:42 tags:post:43# Tags in post 42 but not in post 43
SCARD tags:post:42# 4 (cardinality)Sorted Sets (ZSET)
Section titled “Sorted Sets (ZSET)”Ordered collections where each member has an associated score:
ZADD leaderboard 1500 "player1" 2000 "player2" 1800 "player3"ZREVRANGE leaderboard 0 -1 WITHSCORES# 1) "player2" 2) 2000# 3) "player3" 4) 1800# 5) "player1" 6) 1500
ZREVRANK leaderboard "player1"# 2 (0-indexed rank from highest)
ZADD leaderboard 2100 "player1"# Update score (O(log N))
# Range queriesZRANGEBYSCORE leaderboard 1500 1900 WITHSCORES# Players with scores between 1500 and 1900
# Leaderboard with paginationZREVRANGE leaderboard 0 9 WITHSCORES# Top 10 playersHashes
Section titled “Hashes”Field-value pairs within a single key:
HSET user:1001 name "Alice" email "alice@example.com" age 30HGET user:1001 name# "Alice"HGETALL user:1001# "name" "Alice" "email" "alice@example.com" "age" "30"HMGET user:1001 name email# "Alice" "alice@example.com"HINCRBY user:1001 age 1# 31Bitmaps
Section titled “Bitmaps”Bit-level operations on strings:
SETBIT user:1001:logins 0 1 # Day 0: logged inSETBIT user:1001:logins 1 1 # Day 1: logged inSETBIT user:1001:logins 2 0 # Day 2: did not log inGETBIT user:1001:logins 0# 1
# Count set bits (cardinality)BITCOUNT user:1001:logins# 2
# Bitwise operationsBITOP AND result:week user:1001:logins user:1002:loginsHyperLogLog
Section titled “HyperLogLog”Probabilistic cardinality estimation with 0.81% standard error, using only 12KB:
PFADD pageviews:2024-01-15 "user1" "user2" "user3" "user1"PFCOUNT pageviews:2024-01-15# 3 (deduplicated)
PFMERGE pageviews:2024-01-15-to-20 pageviews:2024-01-15 pageviews:2024-01-16Geospatial
Section titled “Geospatial”GEOADD locations 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"GEORADIUS locations 15 37 100 km COUNT 3# Points within 100km of (15, 37)GEODIST locations "Palermo" "Catania" km# 166.2742Key Management
Section titled “Key Management”TTL and Expiration
Section titled “TTL and Expiration”SETEX key 3600 "value" # Set with 1-hour TTLEXPIRE existing_key 1800 # Set TTL on existing keyTTL key # Remaining seconds (-1 = no expiry, -2 = key not found)PTTL key # Remaining millisecondsPERSIST key # Remove TTL
# Pattern: session with sliding expiry# On each access: EXPIRE session:abc123 1800Eviction Policies
Section titled “Eviction Policies”When maxmemory is reached, Redis uses the configured policy to evict keys:
| Policy | Behavior | Best For |
|---|---|---|
noeviction | Return errors on write commands | Data must not be lost |
allkeys-lru | Evict least recently used keys (any key) | General-purpose caching |
allkeys-lfu | Evict least frequently used keys (Redis 4+) | Better than LRU for hot data |
volatile-lru | Evict LRU among keys with TTL set | Cache with important permanent keys |
volatile-lfu | Evict LFU among keys with TTL set | Cache with important permanent keys |
allkeys-random | Evict random keys | Uniform access patterns |
volatile-random | Evict random keys with TTL set | Uniform access with permanent data |
volatile-ttl | Evict keys with shortest TTL | Time-based cache |
Persistence
Section titled “Persistence”RDB Snapshots
Section titled “RDB Snapshots”RDB creates point-in-time snapshots of the dataset as binary dump files:
save 900 1 # Save after 900 seconds if at least 1 key changedsave 300 10 # Save after 300 seconds if at least 10 keys changedsave 60 10000 # Save after 60 seconds if at least 10000 keys changed
dbfilename dump.rdbdir /var/lib/redisrdbcompression yesrdbchecksum yesRDB snapshots use a fork-based approach: the main process forks a child that writes the dump to Disk. The parent process continues serving requests using copy-on-write semantics. This means RDB Snapshots are non-blocking for reads but may cause latency spikes during fork if the dataset is Large.
AOF (Append Only File)
Section titled “AOF (Append Only File)”AOF logs every write command to a file, providing better durability than RDB:
appendonly yesappendfilename "appendonly.aof"appendfsync everysec # fsync once per second (default, good balance)# appendfsync always # fsync every write (safest, slowest)# appendfsync no # Let OS decide when to fsync (fastest, least safe)AOF Rewrite
Section titled “AOF Rewrite”AOF files grow over time because every write is appended. Redis periodically rewrites the AOF to Create a minimal file that produces the same dataset state:
auto-aof-rewrite-percentage 100 # Trigger rewrite when AOF is 2x the last rewrite sizeauto-aof-rewrite-min-size 64mb # Minimum size to trigger rewritebgrewriteaof # Manual triggerMixed Persistence (Redis 4+)
Section titled “Mixed Persistence (Redis 4+)”aof-use-rdb-preamble yesThe AOF file starts with an RDB snapshot (fast loading) followed by AOF incremental changes (fine-grained durability). This combines the advantages of both approaches.
| Feature | RDB | AOF | Mixed |
|---|---|---|---|
| Durability | Point-in-time only | Every write (configurable) | Good |
| File size | Compact | Grows over time | Compact + small tail |
| Recovery speed | Fast (binary load) | Slow (replay commands) | Fast |
| Write overhead | Fork during snapshot | Every write logged | Moderate |
| Best for | Backup, replication | Maximum durability | General purpose |
Replication
Section titled “Replication”Master-Replica
Section titled “Master-Replica”# On the replica:REPLICAOF master.host 6379# Or in redis.conf:# replicaof master.host 6379# masterauth your_passwordflowchart LR
A[Client] -->|Write| B[Master]
A -->|Read| B
A -->|Read| C[Replica 1]
A -->|Read| D[Replica 2]
B -->|Async Replication| C
B -->|Async Replication| DReplication is asynchronous by default. The replica acknowledges writes to the master, but the Master does not wait for replicas to confirm. This means data can be lost if the master fails before Propagating writes to replicas.
Partial Resynchronization (PSYNC)
Section titled “Partial Resynchronization (PSYNC)”Redis uses a replication backlog (configurable size) on the master. If a replica disconnects and Reconnects within the backlog window, it can resume from where it left off (partial Resynchronization). If the disconnect was too long, a full resynchronization is required.
# Master configurationrepl-backlog-size 10mbrepl-backlog-ttl 3600 # Keep backlog for 1 hour after last replica disconnectRead-Only Replicas
Section titled “Read-Only Replicas”Replicas accept reads by default but reject writes. Configure read behavior:
# On the replicareplica-read-only yes # Reject writes (default)replica-serve-stale-data yes # Serve stale data when disconnected from masterRedis Sentinel
Section titled “Redis Sentinel”Sentinel provides automatic failover for master-replica setups:
# sentinel.conf (run on 3+ independent nodes for quorum)sentinel monitor mymaster 10.0.0.1 6379 2sentinel down-after-milliseconds mymaster 5000sentinel failover-timeout mymaster 60000sentinel parallel-syncs mymaster 1sentinel auth-pass mymaster your_password| Parameter | Meaning |
|---|---|
monitor | Master name, IP, port, quorum (votes needed) |
down-after-milliseconds | Mark master as down after this many ms |
failover-timeout | Wait this long between failovers |
parallel-syncs | How many replicas to resync at once during failover |
Sentinel also acts as a configuration provider: clients connect to Sentinel to discover the current Master address.
Redis Cluster
Section titled “Redis Cluster”Redis Cluster provides horizontal partitioning (sharding) across multiple nodes:
Hash Slots
Section titled “Hash Slots”Redis Cluster uses 16,384 hash slots. Each key is assigned a slot via CRC16(key) % 16384. Each Shard (master node) owns a contiguous range of slots.
# Create a cluster (requires at least 6 nodes: 3 masters + 3 replicas)redis-cli --cluster create \ 10.0.0.1:7000 10.0.0.2:7000 10.0.0.3:7000 \ 10.0.0.4:7000 10.0.0.5:7000 10.0.0.6:7000 \ --cluster-replicas 1Hash Tags
Section titled “Hash Tags”Keys with the same hash tag {tag} are placed on the same slot:
SET user:1001:profile "data"SET user:1001:settings "data"# These go to different slots (CRC16 of entire key)
SET {user:1001}:profile "data"SET {user:1001}:settings "data"# These go to the SAME slot (CRC16 of "user:1001")Hash tags enable multi-key operations on the same slot:
MGET {user:1001}:profile {user:1001}:settings # Works (same slot)MGET user:1001:profile user:1001:settings # ERROR: keys in different slotsGossip Protocol
Section titled “Gossip Protocol”Cluster nodes communicate via a gossip protocol on port port + 10000. Each node periodically pings A few random nodes and exchanges cluster state information (node status, slot mapping, config Epoch). This allows the cluster to detect failures and trigger failover without a centralized Coordinator.
Resharding
Section titled “Resharding”# Move 100 slots from node 1 to node 4redis-cli --cluster reshard 10.0.0.1:7000 \ --cluster-from 10.0.0.1:7000 \ --cluster-to 10.0.0.4:7000 \ --cluster-slots 100 \ --cluster-yesPub/Sub
Section titled “Pub/Sub”# PublisherPUBLISH channel:orders "{"order_id": 42, "status": "created"}'
# SubscriberSUBSCRIBE channel:orders# Messages are delivered to all current subscribers# Messages are NOT persisted: if no subscriber is listening, the message is lost
# Pattern subscriptionPSUBSCRIBE channel:orders:*# Matches channel:orders:created, channel:orders:shipped, etc.Limitations
Section titled “Limitations”- Messages are fire-and-forget: no persistence, no delivery guarantees
- If a subscriber disconnects, it misses messages during the disconnect
- No message backlog for new subscribers
- For reliable messaging, use Redis Streams instead
Streams (Redis 5+)
Section titled “Streams (Redis 5+)”Streams provide a persistent, append-only log with consumer groups:
# Add entries to a streamXADD stream:orders * order_id 42 customer_id 1001 total 299.99# Returns: "1697123456789-0" (timestamp-sequence ID)
# Read entriesXRANGE stream:orders - +XREVRANGE stream:orders + - COUNT 10
# Consumer groupsXGROUP CREATE stream:orders order_processor 0 MKSTREAM
# Consumer reads from groupXREADGROUP GROUP order_processor worker1 COUNT 1 BLOCK 5000 STREAMS stream:orders ># ">" means: deliver new messages (unread)
# Acknowledge processingXACK stream:orders order_processor 1697123456789-0
# View pending entries (delivered but not acknowledged)XPENDING stream:orders order_processorsequenceDiagram
participant P as Producer
participant S as Stream
participant W1 as Worker 1
participant W2 as Worker 2
P->>S: XADD stream:orders * ...
P->>S: XADD stream:orders * ...
P->>S: XADD stream:orders * ...
W1->>S: XREADGROUP GROUP g worker1 COUNT 2
S-->>W1: msg1, msg2
W2->>S: XREADGROUP GROUP g worker2 COUNT 2
S-->>W2: msg3
W1->>S: XACK msg1
W2->>S: XACK msg3Consumer Group Features
Section titled “Consumer Group Features”- Load balancing: messages distributed across consumers in the group
- Message acknowledgment: consumers must XACK after processing
- Pending entries list (PEL): tracks delivered but unacknowledged messages
- Claim: reassign messages from a dead consumer to a live one
# Claim messages from a dead consumer (idle for 60s)XCLAIM stream:orders order_processor worker2 60000 1697123456789-0Transactions
Section titled “Transactions”MULTISET key1 "value1"SET key2 "value2"INCR counterEXEC# All commands execute atomically
# DiscardMULTISET key1 "value1"DISCARD# No commands executed
# Watch (optimistic locking)WATCH account:1GET account:1# "1000"# ... application logic ...MULTISET account:1 "900"EXEC# If account:1 was modified by another client between WATCH and EXEC,# EXEC returns nil (transaction aborted)Transaction Limitations
Section titled “Transaction Limitations”- All commands are queued and executed sequentially after
EXEC - No conditional logic inside a transaction
WATCHprovides optimistic locking but requires retry on conflict- Transactions are not rolled back on errors within
EXEC(partial execution)
Lua Scripting
Section titled “Lua Scripting”Lua scripts execute atomically on the server:
EVAL 'local current = redis.call("GET", KEYS[1])if current and tonumber(current) >= tonumber(ARGV[1]) then redis.call("DECRBY", KEYS[1], ARGV[1]) return 1else return 0end' 1 account:balance 100# Load script once, execute multiple times (more efficient)SCRIPT LOAD 'return redis.call("GET", KEYS[1])'# Returns: "sha1hash"EVALSHA sha1hash 1 mykeyLua Script Rules
Section titled “Lua Script Rules”- Scripts are atomic (no other commands run during script execution)
- Scripts should be fast: long-running scripts block the entire Redis instance
- All keys accessed by a script must be passed via
KEYSarray (not hardcoded) - In Redis Cluster, all keys must be on the same hash slot
Pipelines
Section titled “Pipelines”Pipelines batch multiple commands into a single round-trip:
import redis
r = redis.Redis(host='localhost', port=6379)
pipe = r.pipeline()for i in range(10000): pipe.set(f"key:{i}", f"value:{i}")pipe.execute()# 1 round-trip instead of 10000Performance comparison:
| Method | 10,000 commands | Latency (approx) |
|---|---|---|
| Individual | 10,000 RTTs | ~10s (1ms/RTT) |
| Pipeline | 1 RTT | ~50ms |
| Lua script | 1 RTT | ~30ms |
Memory Optimization
Section titled “Memory Optimization”Encoding Types
Section titled “Encoding Types”Redis automatically selects memory-efficient encodings based on value characteristics:
| Type | Encoding | When Used | Memory per element |
|---|---|---|---|
| Hash | ziplist | <= 512 fields, each <= 64 bytes | ~2 bytes |
| Hash | hashtable | Exceeds ziplist thresholds | ~60 bytes |
| List | quicklist | Always (ziplist nodes in linked list) | ~8 bytes |
| Set | intset | All integers, count <= 512 | ~4 bytes |
| Set | hashtable | Non-integers or count > 512 | ~60 bytes |
| Sorted Set | ziplist | <= 128 elements, each <= 64 bytes | ~8 bytes |
| Sorted Set | skiplist | Exceeds ziplist thresholds | ~60 bytes |
Hash Tags for Related Data
Section titled “Hash Tags for Related Data”# Instead of separate keys:SET user:1001:name "Alice"SET user:1001:email "alice@example.com"
# Use a hash (more memory-efficient):HSET user:1001 name "Alice" email "alice@example.com"Object Encoding Debugging
Section titled “Object Encoding Debugging”MEMORY USAGE key # Bytes used by keyDEBUG OBJECT key # Shows encoding typeOBJECT ENCODING key # Returns: ziplist, hashtable, intset, etc.Common Patterns
Section titled “Common Patterns”Caching
Section titled “Caching”# Cache-aside patternGET cache:user:1001# If nil: fetch from DB, then SET cache:user:1001 "data" EX 300Rate Limiting (Token Bucket via Lua)
Section titled “Rate Limiting (Token Bucket via Lua)”-- KEYS[1] = rate_limit:user:1001-- ARGV[1] = limit (e.g., 10)-- ARGV[2] = window (e.g., 60 seconds)
local key = KEYS[1]local limit = tonumber(ARGV[1])local window = tonumber(ARGV[2])
local current = redis.call("INCR", key)if current == 1 then redis.call("EXPIRE", key, window)end
if current > limit then return 0 -- rejectedelse return current -- remainingendLeaderboard
Section titled “Leaderboard”ZADD leaderboard 1500 "player1"ZINCRBY leaderboard 50 "player1"ZREVRANGE leaderboard 0 9 WITHSCORESZREVRANK leaderboard "player1"Session Store
Section titled “Session Store”SETEX session:abc123 1800 '{"user_id": 1001, "role": "admin"}'GET session:abc123# On logout: DEL session:abc123# On access: EXPIRE session:abc123 1800 (sliding expiry)Job Queue
Section titled “Job Queue”# ProducerLPUSH queue:jobs '{"type": "email", "to": "user@example.com"}'
# Consumer (blocking)BRPOP queue:jobs 30
# Failed jobsLPUSH queue:jobs:failed job_payloadCommon Pitfalls
Section titled “Common Pitfalls”Using KEYS in Production
Section titled “Using KEYS in Production”KEYS pattern* scans the entire keyspace and blocks Redis during the scan. On a large dataset, this Can cause seconds of latency:
# WRONG: blocks for seconds on large datasetsKEYS user:*
# RIGHT: incremental scanSCAN 0 MATCH user:* COUNT 100# Returns cursor and batch of keys# Continue with SCAN <cursor> MATCH user:* COUNT 100Not Setting maxmemory
Section titled “Not Setting maxmemory”Without maxmemoryRedis consumes all available RAM and triggers the OS OOM killer, which Terminates the Redis process (and loses all non-persisted data). Always set maxmemory and an Appropriate eviction policy.
Large Keys
Section titled “Large Keys”Keys larger than 10KB can cause latency spikes because Redis processes them atomically on a single Thread. A 100MB string takes ~100ms to serialize, blocking all other commands during that time.
# Find large keysredis-cli --bigkeys# Or use MEMORY USAGEredis-cli MEMORY USAGE mykeyPub/Sub Message Loss
Section titled “Pub/Sub Message Loss”Pub/sub does not persist messages. If a subscriber disconnects, it misses messages. If no subscriber Is listening when a message is published, the message is lost entirely. Use Streams for reliable Messaging.
Blocking Commands Without Timeouts
Section titled “Blocking Commands Without Timeouts”BLPOP``BRPOP``XREADGROUP BLOCKAnd BRPOPLPUSH without timeouts block the connection Indefinitely. Always specify a timeout:
BLPOP queue:tasks 30 # Timeout after 30 secondsRedis Configuration Deep-Dive
Section titled “Redis Configuration Deep-Dive”Critical Configuration Parameters
Section titled “Critical Configuration Parameters”# redis.conf - key parameters for production
# Networkbind 127.0.0.1 192.168.1.100 # Bind to specific interfacesport 6379protected-mode yes # Reject connections from unbound interfacestcp-backlog 511 # Connection queue (increase for high-conn environments)timeout 0 # Close idle clients after N seconds (0 = never)
# Memorymaxmemory 4gbmaxmemory-policy allkeys-lrumaxmemory-samples 5 # LRU sample size (higher = more accurate but slower)
# Persistencesave 900 1save 300 10save 60 10000appendonly yesappendfsync everysec
# Securityrequirepass your_strong_password # Authenticationrename-command FLUSHDB "" # Disable dangerous commandsrename-command FLUSHALL ""rename-command DEBUG ""
# Loggingloglevel noticelogfile /var/log/redis/redis.log
# Slow queries (log queries exceeding threshold)slowlog-log-slower-than 10000 # 10ms in microsecondsslowlog-max-len 128 # Keep last 128 slow queriesSlow Query Log
Section titled “Slow Query Log”# View slow queriesredis-cli SLOWLOG GET 10
# Slow log lengthredis-cli SLOWLOG LEN
# Reset slow logredis-cli SLOWLOG RESET
# Configure thresholdredis-cli CONFIG SET slowlog-log-slower-than 5000 # 5msRedis Sentinel Deep-Dive
Section titled “Redis Sentinel Deep-Dive”Sentinel Architecture
Section titled “Sentinel Architecture” ┌─────────────┐ │ Sentinel 1 │ └──────┬──────┘ │ gossip ┌──────┴──────┐ │ Sentinel 2 │ └──────┬──────┘ │ gossip┌───────┐ │ ┌───────┐│ Master│◄──────┴──────►│ Rep1 │└───┬───┘ └───────┘ │ async replication┌───┴───┐│ Rep2 │└───────┘Sentinel Commands
Section titled “Sentinel Commands”# Check master statusredis-cli -p 26379 SENTINEL master mymaster
# Check replicasredis-cli -p 26379 SENTINEL replicas mymaster
# Check sentinel peersredis-cli -p 26379 SENTINEL sentinels mymaster
# Get current master address (for client connection)redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# Force failover (for testing)redis-cli -p 26379 SENTINEL failover mymasterSentinel Configuration Best Practices
Section titled “Sentinel Configuration Best Practices”# Minimum 3 Sentinel instances for quorum (prevents split-brain)# Deploy on separate machines from the Redis servers# Set quorum to (number_of_sentinels / 2) + 1
sentinel monitor mymaster 10.0.0.1 6379 2sentinel down-after-milliseconds mymaster 5000sentinel failover-timeout mymaster 60000sentinel parallel-syncs mymaster 1Redis Cluster Operations
Section titled “Redis Cluster Operations”Cluster Management
Section titled “Cluster Management”# Create a cluster with 3 masters and 3 replicasredis-cli --cluster create \ 10.0.0.1:7000 10.0.0.2:7000 10.0.0.3:7000 \ 10.0.0.4:7000 10.0.0.5:7000 10.0.0.6:7000 \ --cluster-replicas 1
# Check cluster statusredis-cli -c -p 7000 CLUSTER INFO
# List cluster nodesredis-cli -c -p 7000 CLUSTER NODES
# Check slot distributionredis-cli -c -p 7000 CLUSTER COUNTKEYSINSLOT 0redis-cli -c -p 7000 CLUSTER GETKEYSINSLOT 0 10Cluster Limitations
Section titled “Cluster Limitations”| Limitation | Value | Workaround |
|---|---|---|
| Maximum keys | 2^34 | Use sharding across clusters |
| Minimum master nodes | 3 | Required for quorum |
| Multi-key operations | Same slot only | Use hash tags {key} |
| Database count | 1 (database 0) | Use key prefixes for namespaces |
| SELECT in Lua scripts | Not supported | Use redis.call() for reads |
| Pipelining across slots | Not supported | Pipeline to the correct node directly |
Handling MOVED and ASK Redirects
Section titled “Handling MOVED and ASK Redirects”When a client sends a command to the wrong node, the node responds with a MOVED or ASK redirect:
# MOVED: the slot has permanently moved to another node (resend to new node)# ASK: the slot is temporarily on another node (during resharding)Most Redis client libraries handle redirects automatically when cluster-enabled: true is Configured.
Redis Security
Section titled “Redis Security”Authentication and ACLs
Section titled “Authentication and ACLs”# Legacy: requirepass (single password for all users)requirepass mypassword
# Modern: ACLs (Redis 6+)# Create a user with specific permissionsACL SETUSER app_user on +@read +@connection -@dangerous ~app:* &my_password
# Create a read-only userACL SETUSER readonly on +@read ~* &readonly_pass
# List usersACL LIST
# Show user detailsACL WHOAMIACL GETUSER app_user
# ACL categories:# +@read - all read commands# +@write - all write commands# +@admin - administrative commands# +@dangerous - dangerous commands (FLUSH, DEBUG, etc.)# +@connection - client management commands# ~pattern - allowed key patterns# &password - user passwordNetwork Security
Section titled “Network Security”# Bind to specific interfacesbind 127.0.0.1
# Disable protected-mode if binding to non-loopback (requires auth)protected-mode yes
# TLS encryption (Redis 6+)tls-port 6379port 0tls-cert-file /etc/redis/server.crttls-key-file /etc/redis/server.keytls-ca-cert-file /etc/redis/ca.crttls-auth-clients optional # or 'yes' for mTLSRedis Performance Benchmarking
Section titled “Redis Performance Benchmarking”# Built-in benchmarkredis-benchmark -h localhost -p 6379 -c 50 -n 100000
# Test specific commandsredis-benchmark -t set,get,lpush,lpop -n 100000 -c 50
# Test pipeline moderedis-benchmark -t set -n 100000 -c 50 -P 16
# Test with larger valuesredis-benchmark -t set -n 10000 -c 50 -d 1024 # 1KB valuesPerformance Expectations
Section titled “Performance Expectations”| Command | Single-Thread Throughput (approx) | Notes |
|---|---|---|
| SET | 80,000-120,000 ops/sec | Varies by value size |
| GET | 100,000-150,000 ops/sec | |
| LPUSH/LPOP | 80,000-120,000 ops/sec | |
| SADD/SISMEMBER | 80,000-120,000 ops/sec | |
| ZADD/ZRANGE | 60,000-100,000 ops/sec | Depends on sorted set size |
| MGET (10 keys) | 40,000-60,000 ops/sec | Amortized per key |
| Pipeline (16) | 500,000-800,000 ops/sec | 16x improvement from pipelining |
Redis Memory Analysis
Section titled “Redis Memory Analysis”# Memory usage summaryredis-cli INFO memory
# Memory usage of a specific keyredis-cli MEMORY USAGE mykey
# Largest keys in the databaseredis-cli --bigkeys
# Memory profiler (Redis 4+)redis-cli MEMORY DOCTORredis-cli MEMORY PURGE # Clean up expired keys immediatelyredis-cli MEMORY STATS # Per-allocator statsSummary
Section titled “Summary”This topic covers the essential chemistry of redis deep dive, including key reactions, underlying theories, and practical applications.
Key concepts include:
- key chemical principles and theories
- mathematical relationships in chemistry
- practical techniques and apparatus
- applications of chemistry in industry
- environmental and ethical considerations
Mastery of these concepts requires both theoretical understanding and the ability to apply knowledge to unfamiliar contexts, particularly in calculation and practical questions.
Worked Examples
Section titled “Worked Examples”Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.