Redis Hashes

Hashes are maps between string fields and string values—perfect for representing objects. They're memory-efficient when storing many small key-value pairs and provide O(1) access to individual fields.

Key Characteristics

• Can store up to 4 billion field-value pairs • Memory-optimized for small hashes (ziplist encoding) • Supports partial updates without reading/writing entire object • Ideal for user profiles, product details, configuration objects

Basic Operations

# Set and get fields
HSET user:1000 name "Alice" email "alice@example.com" age 28
HGET user:1000 name                     # Get single field → "Alice"
HMGET user:1000 name email              # Get multiple fields
HGETALL user:1000                       # Get all field-value pairs

# Check field count
HLEN user:1000                          # Number of fields → 3

Incrementing Numeric Fields

Hash fields can store integers and floats that Redis can increment atomically.

HSET user:1000 age 28 balance 100.50

HINCRBY user:1000 age 1                 # Increment age → 29
HINCRBY user:1000 age -5                # Decrement age → 24
HINCRBYFLOAT user:1000 balance 99.50    # Add to balance → 200.00
HINCRBYFLOAT user:1000 balance -50.25   # Subtract → 149.75

Field Existence and Deletion

HEXISTS user:1000 phone                 # Check if field exists → 0
HSETNX user:1000 phone "555-1234"       # Set only if field doesn't exist
HDEL user:1000 phone                    # Delete field
HDEL user:1000 field1 field2 field3     # Delete multiple fields

Metadata Operations

HKEYS user:1000                         # Get all field names
HVALS user:1000                         # Get all values
HLEN user:1000                          # Count of fields → 3
HSTRLEN user:1000 name                  # Length of field value

Scanning Large Hashes

Use HSCAN for non-blocking iteration over large hashes.

# Iterate with cursor (non-blocking)
HSCAN user:1000 0 COUNT 10              # Start from cursor 0
HSCAN user:1000 17 COUNT 10             # Continue from returned cursor
HSCAN user:1000 0 MATCH email* COUNT 10 # Filter by pattern

Use Case: User Profiles

Store user attributes with granular field updates.

# Create user profile
HSET user:1000
    username "alice"
    email "alice@example.com"
    created_at "2024-01-15"
    login_count 0
    premium false

# Update specific fields without touching others
HINCRBY user:1000 login_count 1
HSET user:1000 last_login "2024-01-16T10:30:00Z"
HSET user:1000 premium true

# Get profile
HGETALL user:1000

Use Case: Shopping Cart

Product IDs as fields, quantities as values.

cart_key = "cart:user:123"

# Add items
HSET cart_key "product:abc" 2           # 2x Product ABC
HSET cart_key "product:xyz" 1           # 1x Product XYZ

# Update quantity
HINCRBY cart_key "product:abc" 1        # Add one more → 3
HINCRBY cart_key "product:abc" -1       # Remove one → 2

# Remove item
HDEL cart_key "product:xyz"

# Get cart contents
HGETALL cart_key

# Clear cart
DEL cart_key

Use Case: Daily Statistics

Multiple counters under one key, organized by date.

stats_key = "stats:page:home"

# Increment daily views
HINCRBY stats_key "2024-01-15" 1
HINCRBY stats_key "2024-01-16" 1
HINCRBY stats_key "2024-01-16" 1

# Get all daily counts
HGETALL stats_key
# Returns: {"2024-01-15": "1", "2024-01-16": "2"}

# Get specific day
HGET stats_key "2024-01-16"

Memory Efficiency

Hashes use ziplist encoding when small, which is very memory-efficient. Configure thresholds in redis.conf:

# redis.conf settings
hash-max-ziplist-entries 512    # Max fields for ziplist
hash-max-ziplist-value 64       # Max field/value size for ziplist

# Check encoding
OBJECT ENCODING user:1000       # → "ziplist" or "hashtable"
MEMORY USAGE user:1000          # Bytes used by key
Knowledge is power.