Redis Strings
Strings are the most basic Redis data type. A Redis string can hold any kind of data: text, serialized JSON, binary data like images, or even integers and floats that Redis can manipulate atomically.
Key Characteristics
• Maximum size: 512 MB per string • Binary-safe: can store any binary data • Supports atomic increment/decrement for numeric values • Perfect for caching, counters, rate limiting, and session storage
Basic Operations
# Store and retrieve strings
SET user:1:name "John Doe" # Store a string
GET user:1:name # Retrieve: "John Doe"
SETNX user:1:name "Jane" # Set only if key doesn't exist (returns 0)
SETEX session:abc123 3600 "user_data" # Set with 1-hour expiration
# Multiple keys at once
MSET user:1:city "NYC" user:1:age "30" # Set multiple keys atomically
MGET user:1:name user:1:city user:1:age # Get multiple valuesAtomic Counters
Redis strings can store integers and provide atomic increment/decrement operations—perfect for counters, rate limiters, and sequences.
SET page:views 0
INCR page:views # Increment by 1 → 1
INCRBY page:views 100 # Increment by 100 → 101
DECR page:views # Decrement by 1 → 100
DECRBY page:views 50 # Decrement by 50 → 50
INCRBYFLOAT price:item1 0.99 # Floating-point increment
# Get and set atomically
GETSET counter "0" # Returns old value, sets new
GETDEL temp:key # Get value and delete keyBit Operations
Treat strings as bit arrays for memory-efficient boolean flags, bloom filters, and user tracking.
SETBIT user:1:features 0 1 # Set bit 0 to 1 (feature enabled)
SETBIT user:1:features 1 1 # Set bit 1 to 1
GETBIT user:1:features 0 # Get bit 0 → 1
BITCOUNT user:1:features # Count set bits → 2
# Bit operations across keys
BITOP AND result key1 key2 # Bitwise AND
BITOP OR result key1 key2 # Bitwise OR
BITOP XOR result key1 key2 # Bitwise XOR
BITOP NOT result key1 # Bitwise NOT
BITPOS user:1:features 1 # Position of first '1' bitString Manipulation
APPEND user:1:name " Jr." # Append → "John Doe Jr."
STRLEN user:1:name # Length → 12
GETRANGE user:1:name 0 3 # Substring → "John"
SETRANGE user:1:name 5 "Smith" # Replace at offset 5
# Get/set with expiration
SET cache:key "value" EX 3600 # Expires in 1 hour
SET cache:key "value" PX 60000 # Expires in 60 seconds
SET cache:key "value" EXAT 1707000000 # Expires at Unix timestamp
TTL cache:key # Check remaining TTLUse Case: Caching
Store serialized objects, API responses, or rendered HTML with automatic expiration.
# Cache API response for 5 minutes
SET cache:api:users:page1 '{"users":[...]}' EX 300
# Check cache first, then fetch
cached = GET cache:api:users:page1
if cached:
return json.parse(cached)
else:
data = fetch_from_database()
SET cache:api:users:page1 json.stringify(data) EX 300
return dataUse Case: Rate Limiting
Implement sliding window counters with INCR and EXPIRE.
def is_rate_limited(user_id, limit=100, window=60):
key = f"rate:{user_id}"
current = INCR(key)
if current == 1:
EXPIRE(key, window) # Set window on first request
return current > limit
# Usage
if is_rate_limited("user:123"):
return "429 Too Many Requests"Use Case: Distributed Locks
Use SET NX PX for acquiring locks with automatic expiration.
def acquire_lock(resource, owner_id, ttl_ms=30000):
key = f"lock:{resource}"
# NX = only if not exists, PX = milliseconds TTL
result = SET(key, owner_id, "NX", "PX", ttl_ms)
return result == "OK"
def release_lock(resource, owner_id):
key = f"lock:{resource}"
# Only release if we own the lock (use Lua script for atomicity)
if GET(key) == owner_id:
DEL(key)
return True
return False
# Lua script for atomic check-and-delete
EVAL "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock:resource owner_id