Redis Sets
Sets are unordered collections of unique strings. They provide O(1) membership testing and support powerful set operations like union, intersection, and difference.
When Redis Sets Are the Right Choice
Choose sets when uniqueness and fast membership checks matter more than order. They are a natural fit for tags, participant pools, feature flags, friend lists, and unique-visitor tracking.
Key Characteristics
• Unique members only (automatic deduplication) • O(1) add, remove, and membership test • Set operations: union, intersection, difference • Random member selection supported
Basic Operations
# Add members
SADD tags:post:1 "redis" "database" "nosql"
SADD tags:post:1 "redis" # Returns 0 (already exists)
# Check membership
SISMEMBER tags:post:1 "redis" # → 1 (true)
SISMEMBER tags:post:1 "mysql" # → 0 (false)
SMISMEMBER tags:post:1 "redis" "mysql" # Check multiple → [1, 0]
# Get all members
SMEMBERS tags:post:1
# Count members
SCARD tags:post:1 # → 3Remove Members
SREM tags:post:1 "nosql" # Remove one member
SREM tags:post:1 "tag1" "tag2" "tag3" # Remove multiple
# Pop random member(s)
SPOP tags:post:1 # Remove and return 1 random
SPOP tags:post:1 3 # Remove and return 3 randomSet Operations
Powerful operations for combining and comparing sets.
SADD tags:post:1 "redis" "database" "nosql"
SADD tags:post:2 "redis" "caching" "performance"
# Intersection (common elements)
SINTER tags:post:1 tags:post:2 # → ["redis"]
# Union (all unique elements)
SUNION tags:post:1 tags:post:2 # → all unique tags
# Difference (in first but not in second)
SDIFF tags:post:1 tags:post:2 # → ["database", "nosql"]
SDIFF tags:post:2 tags:post:1 # → ["caching", "performance"]Store Set Operation Results
# Store intersection in new key
SINTERSTORE common:tags tags:post:1 tags:post:2
# Store union in new key
SUNIONSTORE all:tags tags:post:1 tags:post:2
# Store difference in new key
SDIFFSTORE unique:post1 tags:post:1 tags:post:2Random Selection
# Get random member(s) without removing
SRANDMEMBER tags:post:1 # 1 random member
SRANDMEMBER tags:post:1 3 # 3 random members
SRANDMEMBER tags:post:1 -3 # 3 random (may repeat)
# Pop random member(s) (removes them)
SPOP tags:post:1 # Pop 1
SPOP tags:post:1 3 # Pop 3Move Between Sets
# Atomically move member between sets
SMOVE source_set dest_set "member"
# Example: Move user from pending to approved
SMOVE users:pending users:approved "user:123"Scanning Large Sets
# Non-blocking iteration
SSCAN tags:post:1 0 COUNT 100 # Start from cursor 0
SSCAN tags:post:1 17 COUNT 100 # Continue from cursor
SSCAN tags:post:1 0 MATCH redis* COUNT 100 # With pattern filterUse Case: Social Graph
Track followers/following relationships.
# Following relationships
SADD following:alice "bob" "charlie" "dave"
SADD following:bob "alice" "eve"
SADD followers:bob "alice" "charlie"
# Find mutual follows (who both Alice and Bob follow)
SINTER following:alice following:bob
# Find all people in extended network
SUNION following:alice following:bob
# Check if Alice follows Bob
SISMEMBER following:alice "bob"
# Get follow counts
SCARD following:alice # Following count
SCARD followers:alice # Followers countUse Case: Unique Visitors
# Track daily unique visitors
today = "2024-01-15"
def track_visitor(visitor_id):
key = f"visitors:{today}"
SADD(key, visitor_id)
EXPIRE(key, 86400 * 7) # Keep for 7 days
def get_unique_count(date):
return SCARD(f"visitors:{date}")
def get_weekly_uniques():
keys = [f"visitors:{day}" for day in last_7_days()]
temp_key = "visitors:week:temp"
SUNIONSTORE(temp_key, *keys)
count = SCARD(temp_key)
DEL(temp_key)
return countUse Case: Tagging System
# Tag posts
SADD post:123:tags "redis" "tutorial" "database"
SADD post:456:tags "redis" "performance" "caching"
# Reverse index: posts by tag
SADD tag:redis:posts "123" "456"
SADD tag:tutorial:posts "123"
# Find posts with multiple tags
SINTER tag:redis:posts tag:tutorial:posts
# Find all posts with any of these tags
SUNION tag:redis:posts tag:caching:postsUse Case: Random Giveaway
# Add participants
SADD giveaway:123 "user:1" "user:2" "user:3" "user:4" "user:5"
# Pick winner (removes from set)
winner = SPOP giveaway:123
print(f"Winner: {winner}")
# Pick 3 winners
winners = SPOP giveaway:123 3
# Preview random participants without removing
preview = SRANDMEMBER giveaway:123 5Common Redis Set Mistakes
A common mistake is expecting stable order from a set. Redis sets are unordered, so if display order, ranking, or recency matters, a sorted set or list is usually the correct type instead.
Related
Compare sets with hashes, lists, and sorted sets before choosing a membership model.
Use sorted sets when uniqueness still matters but members also need ranking or score ordering.
Strings work better when you only need one value per key instead of a unique member collection.
Useful when cleaning or normalizing set members before insertion.