The Aspire.StackExchange.Redis component registers an IConnectionMultiplexer in your dependency injection container for connecting to Redis servers. It automatically enables health checks, logging, and distributed tracing.
Retrieve the IConnectionMultiplexer instance using dependency injection:
public class ProductsController : ControllerBase{ private readonly IConnectionMultiplexer _redis; public ProductsController(IConnectionMultiplexer redis) { _redis = redis; } [HttpGet("{id}")] public async Task<IActionResult> GetProduct(int id) { var db = _redis.GetDatabase(); var cacheKey = $"product:{id}"; // Try to get from cache var cachedProduct = await db.StringGetAsync(cacheKey); if (cachedProduct.HasValue) { return Ok(JsonSerializer.Deserialize<Product>(cachedProduct)); } // Fetch from database and cache var product = await FetchProductFromDatabase(id); await db.StringSetAsync(cacheKey, JsonSerializer.Serialize(product), TimeSpan.FromMinutes(10)); return Ok(product); }}
public async Task<Product> GetProductAsync(int id){ var db = _redis.GetDatabase(); var key = $"product:{id}"; var cached = await db.StringGetAsync(key); if (cached.HasValue) { return JsonSerializer.Deserialize<Product>(cached); } var product = await _productRepository.GetByIdAsync(id); await db.StringSetAsync(key, JsonSerializer.Serialize(product), TimeSpan.FromMinutes(10)); return product;}
public async Task<bool> AcquireLockAsync(string resource, TimeSpan expiry){ var db = _redis.GetDatabase(); var lockKey = $"lock:{resource}"; var token = Guid.NewGuid().ToString(); return await db.StringSetAsync(lockKey, token, expiry, When.NotExists);}
public async Task SaveSessionAsync(string sessionId, UserSession session){ var db = _redis.GetDatabase(); var key = $"session:{sessionId}"; await db.StringSetAsync(key, JsonSerializer.Serialize(session), TimeSpan.FromHours(1));}
The IConnectionMultiplexer is designed to be reused throughout your application. Never create multiple instances - use dependency injection to share a single instance.
Use appropriate data types
Redis supports multiple data types (strings, hashes, lists, sets, sorted sets). Choose the appropriate type for your use case:
// String for simple valuesawait db.StringSetAsync("key", "value");// Hash for objectsawait db.HashSetAsync("user:1", new HashEntry[] { new HashEntry("name", "John"), new HashEntry("age", "30")});// List for ordered collectionsawait db.ListRightPushAsync("queue", "item");
Set appropriate expiration times
Always set expiration times for cache entries to prevent memory exhaustion:
Implement fallback logic for when Redis is unavailable:
try{ var cached = await db.StringGetAsync(key); if (cached.HasValue) return cached;}catch (RedisException){ // Log and continue without cache}return await FetchFromDatabase();
Use batching for multiple operations
Use batching to reduce round trips:
var batch = db.CreateBatch();var tasks = new List<Task>();foreach (var item in items){ tasks.Add(batch.StringSetAsync(item.Key, item.Value));}batch.Execute();await Task.WhenAll(tasks);