Learn about Redis data structures including Strings, Lists, Sets, Sorted Sets, Hashes, and specialized structures like Streams and Bitmaps. Understand optimal use cases for each structure.
Learn about Redis data structures including Strings, Lists, Sets, Sorted Sets, Hashes, and specialized structures like Streams and Bitmaps. Understand optimal use cases for each structure.
One of Redis's most powerful features is its rich set of built-in data structures. Unlike simple key-value stores that can only
associate string keys with string values, Redis provides specialized data structures that are optimized for different access
patterns and use cases.
Understanding these data structures in depth is essential for leveraging Redis effectively. Each structure has unique
properties, commands, and ideal use cases. By choosing the right data structure for your specific requirements, you can write
more efficient code, reduce complexity, and improve performance.
All Redis data structures store keys as strings, but the values can be different data types.
Keys in Redis have a maximum size of 512 MB, though it's recommended to keep them small for better memory efficiency.
Strings are the most basic Redis data type. Despite the name, they can store any kind of data, including text,
integers, floats, and even binary data like serialized objects or images.
Binary safe
: Can store any binary sequence, up to 512 MB in size
Efficient for numbers
: Redis can recognize string values as integers and perform atomic increment/decrement operations
Various operations
: Set, get, append, substring, and more
Memory efficient
: Small strings (≤ 44 bytes) are stored with the internal object header for optimized memory usage
Description
Time Complexity
SET key value [EX seconds] [NX|XX]
Set key to hold string value, with optional expiration and conditions
Get the string value of key
Increment the integer value of key by one
Decrement the integer value of key by one
APPEND key value
Append value to the string stored at key
GETRANGE key start end
Get substring of string value (inclusive)
O(N) where N is the length of the returned string
MSET key1 value1 key2 value2 ...
Set multiple key-value pairs at once
O(N) where N is the number of keys
Learn about Examples.
1
2# Basic string operations
3SET username "johndoe"
4GET username # Returns "johndoe"
5
6# String with expiration (in seconds)
7SET login_token "a1b2c3" EX 3600
8
9# Numeric operations
10SET counter 10
11INCR counter # Returns 11
12INCRBY counter 5 # Returns 16
13DECR counter # Returns 15
14
15# Multiple operations in one command
16MSET first_name "John" last_name "Doe" age "30"
17MGET first_name last_name age # Returns ["John", "Doe", "30"]
18 1
2# Queue implementation (FIFO - First In First Out)
3RPUSH tasks "send-welcome-email:user123"
4RPUSH tasks "process-payment:order456"
5LPOP tasks # Returns "send-welcome-email:user123"
6
7# Stack implementation (LIFO - Last In First Out)
8LPUSH history "page-3"
9LPUSH history "page-2"
10LPUSH history "page-1"
11LPOP history # Returns "page-1"
12
13# Bounded list (capped collection)
14RPUSH logs "log entry 1"
15RPUSH logs "log entry 2"
16RPUSH logs "log entry 3"
17LTRIM logs 0 9 # Keep only the 10 most recent entries
18
19# Get all elements
20LRANGE logs 0 -1 # -1 means the last element (get all)
21
22# List length
23LLEN tasks # Returns number of items in the list
24 1
2# Track unique visitor IDs
3SADD visitors:20230112 "user:123" "user:456" "user:789"
4SADD visitors:20230112 "user:123" # Adding duplicate has no effect
5SCARD visitors:20230112 # Returns 3
6
7# Test membership
8SISMEMBER visitors:20230112 "user:123" # Returns 1 (true)
9SISMEMBER visitors:20230112 "user:999" # Returns 0 (false)
10
11# Set operations
12SADD active:users "user:123" "user:456" "user:789"
13SADD premium:users "user:456" "user:789" "user:999"
14
15# Intersection (users who are both active and premium)
16SINTER active:users premium:users # Returns ["user:456", "user:789"]
17
18# Union (all users who are either active or premium)
19SUNION active:users premium:users # Returns ["user:123", "user:456", "user:789", "user:999"]
20
21# Difference (active users who are not premium)
22SDIFF active:users premium:users # Returns ["user:123"]
23
24# Store result in a new key
25SINTERSTORE active:premium active:users premium:users
26 1
2# Leaderboard implementation
3ZADD leaderboard 1000 "player:123"
4ZADD leaderboard 2500 "player:456"
5ZADD leaderboard 1800 "player:789"
6
7# Update a score
8ZINCRBY leaderboard 100 "player:123" # Adds 100 points
9
10# Get top 3 players (highest scores)
11ZREVRANGE leaderboard 0 2 WITHSCORES
12
13# Get player rank (0-based)
14ZREVRANK leaderboard "player:456" # Returns 0 (top rank)
15
16# Get players within score range
17ZRANGEBYSCORE leaderboard 1500 2000 WITHSCORES # Returns players with 1500-2000 points
18
19# Get player count within score range
20ZCOUNT leaderboard 1500 2000
21
22# Get player score
23ZSCORE leaderboard "player:123" # Returns 1100
24 : Store cached database queries, API responses, or rendered HTML fragments
Session storage
: Store user session data with an expiration time
: Track page views, API calls, or any numeric metrics
Rate limiting
: Implement API rate limits with expiration
Distributed locks
: Implement simple distributed locks using SET with NX option
Storing serialized objects
: Store JSON, MessagePack, or other serialization formats
For storing structured data, you might be tempted to use strings with serialized JSON. While this works, consider using
Redis Hashes instead for better memory efficiency and the ability to access and modify individual fields without
reading and writing the entire object.
Redis Lists are linked lists of string values, stored in insertion order. They support efficient operations at both ends,
making them ideal for implementing queues, stacks, or bounded collections of elements.
Ordered sequence
: Elements maintain their insertion order
Fast head/tail operations
: O(1) operations for adding/removing elements at either end
Blocking operations
: Support for blocking pops, ideal for work queues
Bounded size
: Can be limited to a maximum length (capped lists)
: Elements can be accessed by position (though not as efficiently as arrays)
Description
Time Complexity
LPUSH key value [value ...]
Insert values at the beginning of the list
O(1) for each element
RPUSH key value [value ...]
Insert values at the end of the list
O(1) for each element
Remove and return the first element
Remove and return the last element
BLPOP key [key ...] timeout
Blocking version of LPOP
LRANGE key start stop
Get a range of elements (inclusive)
O(S+N) where S is start offset and N is number of elements
Get the length of the list
LTRIM key start stop
Trim list to specified range (inclusive)
O(N) where N is the number of elements to be removed
Learn about Examples.
Task queues
: Store tasks to be processed by worker processes
Recent activity
: Track recent actions, comments, or updates
Timeline feeds
: Implement social media timelines with posts in chronological order
Message brokers
: Simple publish/subscribe messaging
: Implement navigation history, undo/redo functionality
Circular buffers
: Limited-size collections with automatic removal of oldest items
Be careful when using LRANGE on very large lists, as it can impact performance. If you only need to iterate through
the entire list, consider using a combination of LPOP/RPOP with LPUSH/RPUSH to process elements one by one.
Redis Sets are unordered collections of unique strings. They provide efficient operations for testing membership,
intersection, union, and difference between collections. Sets are ideal when you need to track unique items or
perform set operations.
Uniqueness guarantee
: Each element can appear only once
No ordering
: Elements are not stored in any particular order
Fast lookups
: O(1) membership testing
Set operations
: Union, intersection, and difference commands
Random element access
: Efficient random sampling from sets
Description
Time Complexity
SADD key member [member ...]
Add members to a set
O(1) for each element
SMEMBERS key
Get all members of a set
O(N) where N is the set size
SISMEMBER key member
Check if member is in set
Get the number of members in set
SREM key member [member ...]
Remove members from set
O(1) for each element
SINTER key [key ...]
Intersection of multiple sets
O(N*M) where N is the size of the smallest set
SUNION key [key ...]
Union of multiple sets
O(N) where N is the total number of elements
SRANDMEMBER key [count]
Get random members from set
O(count) for multiple elements
Learn about Examples.
Unique counting
: Track unique visitors, views, or events
Tagging systems
: Store tags for articles, products, or users
Relationship management
: Store social relationships (friends, followers)
Common interest finding
: Find intersections between user interests
Filtering duplicates
: Ensure uniqueness in data processing pipelines
Random sampling
: Select random items from a collection
Blacklists/whitelists
: Store IP addresses, user IDs for access control
For extremely large sets where memory usage is a concern, consider using HyperLogLog (PFADD, PFCOUNT) instead,
which provides approximate cardinality counting with constant memory usage.
Redis Sorted Sets are similar to Sets, but each member is associated with a score that allows for ordered operations.
Elements are ordered by their score, enabling efficient sorted operations while maintaining uniqueness.
Unique members
: Each element can appear only once
Ordered by score
: Elements are sorted by their associated score
Fast range operations
: Efficient access to ranges by score or rank
Score updates
: Elements can have their scores updated without removing and re-adding
Lexicographical ordering
: When scores are equal, elements are sorted lexicographically
Description
Time Complexity
ZADD key [NX|XX] score member [score member ...]
Add members with scores to sorted set
O(log(N)) for each element
ZRANGE key start stop [WITHSCORES]
Return range of members by index (low to high)
O(log(N)+M) where M is number of elements returned
ZREVRANGE key start stop [WITHSCORES]
Return range of members by index (high to low)
O(log(N)+M) where M is number of elements returned
ZRANGEBYSCORE key min max [WITHSCORES]
Return members with scores within range
O(log(N)+M) where M is number of elements returned
ZRANK key member
Get the rank of member (0-based, ascending)
ZREVRANK key member
Get the rank of member (0-based, descending)
ZSCORE key member
Get the score of member
ZINCRBY key increment member
Increment the score of member
Learn about Examples.
Sorted sets are particularly useful for time-series data when using timestamps as scores:
1
2# Add events with timestamp as score
3ZADD events 1673556267 "login:user123"
4ZADD events 1673556500 "purchase:order456"
5ZADD events 1673557000 "logout:user123"
6
7# Get events from a specific time range
8ZRANGEBYSCORE events 1673556000 1673557000
9
10# Get the latest 5 events
11ZREVRANGE events 0 4
12
13# Remove old events (data retention policy)
14ZREMRANGEBYSCORE events 0 1673555000 # Remove events older than threshold
15 Leaderboards
: Ranking users by score, showing top N users
Priority queues
: Tasks sorted by priority or scheduled execution time
Time-series data
: Events ordered by timestamp
Rate limiters
: Sliding window rate limiting with timestamps
Range queries
: Finding elements with scores in a specific range
Autocomplete systems
: Suggest words based on frequency (score)
Trending analysis
: Tracking popularity with decaying scores
Sorted Sets combine the uniqueness property of Sets with the ordering capability of Lists, making them one of the most
versatile Redis data structures. They're ideal for situations where you need both properties at once.
Redis Hashes are maps between string fields and string values, making them perfect for representing objects.
They're memory efficient and allow access to individual fields without reading or writing the entire object.
Field-value mappings
: Store multiple fields under a single key
Partial updates
: Modify individual fields without affecting others
Memory efficiency
: More space-efficient than storing each field as a separate key
Atomic operations
: Multiple field updates in a single command
Field increment
: Numeric field values can be incremented/decremented
Description
Time Complexity
HSET key field value [field value ...]
Set field(s) to value(s) in hash
O(1) for each field
HGET key field
Get value of a field
HMGET key field [field ...]
Get values of multiple fields
O(1) for each field
HGETALL key
Get all fields and values
O(N) where N is hash size
HDEL key field [field ...]
Delete field(s) from hash
O(1) for each field
HEXISTS key field
Check if field exists
HINCRBY key field increment
Increment integer value of field
Get all fields in hash
O(N) where N is hash size
Get all values in hash
O(N) where N is hash size
Learn about Examples.
1
2# Storing user profile data
3HSET user:123 username "johndoe" email "[email protected]" visits 10
4
5# Setting multiple fields at once
6HMSET user:456 username "janedoe" email "[email protected]" visits 5 created_at 1673556267
7
8# Getting specific fields
9HGET user:123 email # Returns "[email protected]"
10HMGET user:123 username email # Returns ["johndoe", "[email protected]"]
11
12# Getting all fields and values
13HGETALL user:123
14
15# Incrementing numeric fields
16HINCRBY user:123 visits 1 # Increment visit count by 1
17HGET user:123 visits # Returns "11"
18
19# Checking if a field exists
20HEXISTS user:123 phone # Returns 0 (false)
21
22# Deleting fields
23HDEL user:123 visits
24
25# Getting all field names or values
26HKEYS user:123 # Returns ["username", "email"]
27HVALS user:123 # Returns ["johndoe", "[email protected]"]
28 User profiles
: Store user data with multiple attributes
Product information
: Store product details with multiple fields
Session storage
: Store session data with various attributes
Object caching
: Cache database records or API responses
Configuration settings
: Store application configuration
: Store form submissions with multiple fields
Counter groups
: Track multiple related counters together
Hashes are more memory efficient than storing each field as a separate string key, especially for objects
with many small fields. Redis can store small hashes (with small keys and values) in a space-optimized
way that uses less memory.
Beyond the core data structures, Redis offers several specialized structures for specific use cases.
Bitmaps are not a separate data type but a set of bit-oriented operations on string values. They allow efficient
storage and manipulation of binary data, perfect for scenarios like presence indicators or feature flags.
: Real-time analytics, presence tracking, activity monitoring, feature flags
1
2# Set bit at offset (0-based)
3SETBIT active:users 123 1 # Set user ID 123 as active
4
5# Get bit at offset
6GETBIT active:users 123 # Returns 1 if user 123 is active
7
8# Count set bits (population counting)
9BITCOUNT active:users # Count active users
10
11# Bitwise operations
12BITOP AND active:premium active:users premium:users
13BITOP OR all:users active:users inactive:users
14
15# Find first set bit
16BITPOS active:users 1 # Find lowest ID of an active user
17 HyperLogLog is a probabilistic data structure for estimating the cardinality (count of unique elements) of a set.
It uses minimal memory (12KB per key) regardless of the number of elements.
: Unique visitor counting, cardinality estimation for large datasets
1
2# Add elements to HyperLogLog
3PFADD visitors:20230112 "user:123" "user:456" "user:789"
4PFADD visitors:20230113 "user:123" "user:555" "user:789"
5
6# Count unique elements
7PFCOUNT visitors:20230112 # Returns approximate count of unique visitors
8
9# Merge multiple HyperLogLogs
10PFMERGE visitors:week visitors:20230112 visitors:20230113
11PFCOUNT visitors:week # Count unique visitors across both days
12 Geospatial indexes allow storing and querying geographical coordinates (longitude, latitude). They're ideal for
location-based applications like finding nearby places or calculating distances.
: Nearby places, ride-sharing apps, location-based searches
1
2# Add locations (longitude, latitude, name)
3GEOADD locations -73.9857 40.7484 "empire_state"
4GEOADD locations -73.9762 40.7525 "grand_central"
5GEOADD locations -74.0060 40.7128 "one_world_trade"
6
7# Get distance between locations (in km by default)
8GEODIST locations empire_state grand_central km # Returns distance in kilometers
9
10# Find locations within radius
11GEORADIUS locations -73.9857 40.7484 5 km # Find locations within 5km of Empire State
12
13# Find locations within radius of a member
14GEORADIUSBYMEMBER locations empire_state 5 km
15
16# Get coordinates of a location
17GEOPOS locations empire_state
18 Streams (Redis 5.0+) are append-only collections of map-like entries, providing a log data structure ideal for
event sourcing, messaging, and time-series use cases.
: Event sourcing, activity feeds, time-series data, messaging, log processing
1
2# Add entry to stream (auto-generated ID)
3XADD events * type login user_id 123 ip 192.168.1.1
4
5# Add entry with specific ID
6XADD events 1673556267000-0 type purchase user_id 123 product_id 456 amount 29.99
7
8# Read stream entries
9XRANGE events - + COUNT 10 # Read first 10 entries
10XRANGE events 1673556000000-0 1673557000000-0 # Read entries in time range
11
12# Consume new entries (blocking)
13XREAD COUNT 2 BLOCK 5000 STREAMS events $ # Read 2 new entries, block for 5 seconds
14
15# Create consumer groups
16XGROUP CREATE events mygroup $ # Create group starting from newest entry
17
18# Read as consumer group
19XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS events > # Read unprocessed entries
20
21# Acknowledge processed entries
22XACK events mygroup 1673556267000-0
23 Choosing the right Redis data structure for your use case can significantly impact performance, memory usage, and
code complexity. Here's a guide to help you select the most appropriate structure:
If you need to...
Consider using...
Store a single value (string, number, serialized object)
Implement a queue or stack
Store a collection of unique elements
Track top N items or implement a leaderboard
Sorted Set
Store an object with multiple fields
Track binary states for large number of items
Count unique items with minimal memory
HyperLogLog
Store and query geographical locations
Geospatial Index
Process time-ordered events or messaging
When choosing a data structure, consider these performance aspects:
Time complexity
: Check the time complexity of operations you'll use frequently
Memory usage
: Some structures (like Hashes) are more memory-efficient than others
Operation types
: Choose based on whether you need random access, ordered access, or unique elements
: For very large datasets, consider specialized structures like HyperLogLog
Access patterns
: Match the structure to how you'll most frequently access the data
Learn about Advanced Patterns and Techniques.
Complex applications often combine multiple Redis data structures to build sophisticated features:
1
2# User system with profiles, sessions, and relationships
3HSET user:123 username "johndoe" email "[email protected]" # Profile as Hash
4SET session:abc123 123 EX 3600 # Session as String with expiration
5SADD user:123:followers 456 789 # Followers as Set
6ZADD user:123:posts 1673556267 "post:1" 1673556500 "post:2" # Posts as Sorted Set
7
8# E-commerce system with products, inventory, and cart
9HSET product:456 name "Smartphone" price 499.99 # Product as Hash
10INCRBY inventory:456 -1 # Decrement inventory as String counter
11LPUSH cart:123 "product:456" # Cart as List
12ZADD purchases 1673556267 "purchase:789" # Purchase history as Sorted Set
13 Redis transactions allow executing multiple commands atomically:
1
2# Transfer points between users atomically
3MULTI
4ZINCRBY leaderboard -100 "user:123" # Deduct points from one user
5ZINCRBY leaderboard 100 "user:456" # Add points to another user
6EXEC
7
8# Atomic cart checkout process
9MULTI
10LPUSH orders "order:789" # Create order
11DEL cart:123 # Clear cart
12INCRBY inventory:456 -1 # Decrement inventory
13EXEC
14 Lua scripts allow executing complex operations atomically on the Redis server:
1
2# Implementing a rate limiter
3EVAL "
4 local key = KEYS[1]
5 local limit = tonumber(ARGV[1])
6 local window = tonumber(ARGV[2])
7
8 -- Add current timestamp
9 redis.call('ZADD', key, ARGV[3], ARGV[3])
10
11 -- Remove timestamps outside window
12 redis.call('ZREMRANGEBYSCORE', key, 0, ARGV[3] - window)
13
14 -- Count requests in window
15 local count = redis.call('ZCARD', key)
16
17 -- Set expiration
18 redis.call('EXPIRE', key, window)
19
20 -- Return count and limit status
21 return {count, count <= limit}
22" 1 rate:limit:123 10 60 1673556267
23 Implementing a rate limiter with sliding window:
1
2# Record request with timestamp
3ZADD ratelimit:api:123 1673556267 "req1"
4ZADD ratelimit:api:123 1673556270 "req2"
5
6# Remove requests outside window (60 seconds)
7ZREMRANGEBYSCORE ratelimit:api:123 0 1673556210
8
9# Count requests in current window
10ZCARD ratelimit:api:123
11
12# Set expiry on whole key
13EXPIRE ratelimit:api:123 60
14 Organizing keys hierarchically with namespaces:
1
2# Organized key naming convention
3SET user:123:profile:username "johndoe"
4SET user:123:profile:email "[email protected]"
5SET user:123:session:token "abc123"
6SET user:123:preferences:theme "dark"
7
8# Using wildcards to find related keys
9KEYS user:123:*
10
11# Finding specific type of data
12KEYS user:123:session:*
13 Redis data structures provide powerful, flexible building blocks for a wide range of applications. By understanding
the unique properties and use cases of each structure, you can design more efficient and elegant solutions.
Key takeaways from this lesson:
Redis offers a rich set of data structures beyond simple key-value storage
Each data structure has specific operations optimized for different access patterns
Choosing the right structure can significantly impact performance and memory usage
Complex applications often combine multiple data structures for sophisticated features
Advanced patterns like transactions and Lua scripting enable complex atomic operations
In the next lesson, we'll explore Redis persistence and replication mechanisms that ensure data durability
and high availability.
Your progress is saved in this browser, on this device only.