Isaac.

Redis Data Structures

Leverage Redis data structures for efficient caching and messaging.

By EMEPublished: February 20, 2025
redisdata structuresstringslistssetshashes

A Simple Analogy

Redis data structures are like different types of containers. Strings for simple values, lists for queues, sets for uniqueness.


Why Structures?

  • Optimization: Right tool for each use case
  • Performance: Operations optimized per type
  • Flexibility: Different access patterns
  • Efficiency: Memory-efficient storage
  • Operations: Built-in operations per type

Strings

var redis = ConnectionMultiplexer.Connect("localhost:6379");
var db = redis.GetDatabase();

// Set/Get
db.StringSet("user:1:name", "Alice");
var name = db.StringGet("user:1:name");

// Increment
db.StringIncrement("page:views");
var views = db.StringGet("page:views");

// Expiration
db.StringSet("session:123", "token-abc", TimeSpan.FromHours(1));

Lists (Queues)

// Push/Pop
db.ListRightPush("tasks", "task-1");
db.ListRightPush("tasks", "task-2");

var task = db.ListLeftPop("tasks");  // FIFO

// Get range
var allTasks = db.ListRange("tasks", 0, -1);

// Length
var count = db.ListLength("tasks");

// Use case: Job queue
db.ListRightPush("queue:jobs", JsonConvert.SerializeObject(job));
var nextJob = db.ListLeftPop("queue:jobs");

Sets (Unique Items)

// Add/Remove
db.SetAdd("user:1:tags", "csharp");
db.SetAdd("user:1:tags", "azure");
db.SetAdd("user:1:tags", "csharp");  // Duplicate, ignored

// Get all
var tags = db.SetMembers("user:1:tags");

// Check membership
var hasCsharp = db.SetContains("user:1:tags", "csharp");

// Set operations
db.SetAdd("user:2:tags", "csharp");
db.SetAdd("user:2:tags", "devops");

var commonTags = db.SetCombine(SetOperation.Intersect, 
    "user:1:tags", "user:2:tags");

Hashes (Objects)

// Set fields
db.HashSet("user:1", new HashEntry[] {
    new HashEntry("name", "Alice"),
    new HashEntry("email", "alice@example.com"),
    new HashEntry("age", "30")
});

// Get field
var name = db.HashGet("user:1", "name");

// Get all
var user = db.HashGetAll("user:1");
foreach (var entry in user)
{
    Console.WriteLine($"{entry.Name}: {entry.Value}");
}

// Increment
db.HashIncrement("user:1", "posts", 1);

Sorted Sets (Leaderboards)

// Add with score
db.SortedSetAdd("leaderboard", "alice", 1050);
db.SortedSetAdd("leaderboard", "bob", 950);
db.SortedSetAdd("leaderboard", "charlie", 1200);

// Get top 3
var top3 = db.SortedSetRangeByRankWithScores("leaderboard", 0, 2, Order.Descending);

foreach (var entry in top3)
{
    Console.WriteLine($"{entry.Element}: {entry.Score}");
}

// Rank
var rank = db.SortedSetRank("leaderboard", "alice");

Best Practices

  1. Right structure: Match your access pattern
  2. Expiration: Set TTLs to prevent memory bloat
  3. Naming: Use consistent key naming (user:ID:field)
  4. Atomic: Use Lua scripts for multi-step operations
  5. Monitoring: Track memory usage

Related Concepts

  • Caching strategies
  • Pub/Sub messaging
  • Redis Streams
  • Cluster mode

Summary

Redis provides optimized data structures for different use cases: strings for values, lists for queues, sets for uniqueness, hashes for objects.