Caching in C#: Redis, Memcached, and Built-in Solutions
Caching is one of the key tools for performance optimization in modern web applications. In the C# (.NET) ecosystem, developers have access to both built-in mechanisms (IMemoryCache, IDistributedCache) and powerful external solutions (Redis, Memcached). In this article, we will examine their features, compare performance, and provide practical code examples.
1. Built-in .NET Solutions: IMemoryCache and IDistributedCache
ASP.NET Core provides two main interfaces for working with cache: IMemoryCache (local cache in the memory of a single process) and IDistributedCache (abstraction for distributed cache).
IMemoryCache
Ideal for monolithic applications or microservices where synchronization between instances is not required. The cache is stored in the server's RAM.
// Registration in Program.csbuilder.Services.AddMemoryCache();
// Usage in a servicepublic class DataService{ private readonly IMemoryCache _cache;
public DataService(IMemoryCache cache) { _cache = cache; }
public async Task<string> GetExpensiveDataAsync(int id) { string cacheKey = $"data_{id}"; if (_cache.TryGetValue(cacheKey, out string cachedData)) { return cachedData; }
// Emulation of a heavy operation await Task.Delay(500); string data = $"Result for {id}";
var options = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(10)) .SetSlidingExpiration(TimeSpan.FromMinutes(2));
_cache.Set(cacheKey, data, options); return data; }}IDistributedCache
An abstraction that allows connecting various backends (Redis, SQL Server, NCache) without changing the application code. It is registered via AddDistributedRedisCache or AddDistributedSqlServerCache.
// Example with Redisbuilder.Services.AddStackExchangeRedisCache(options =>{ options.Configuration = "localhost:6379"; options.InstanceName = "SampleInstance";});
// Usagepublic class DistributedService{ private readonly IDistributedCache _cache;
public DistributedService(IDistributedCache cache) { _cache = cache; }
public async Task<string> GetDataAsync(string key) { var cached = await _cache.GetStringAsync(key); if (cached != null) return cached;
var data = $"Computed at {DateTime.Now}"; await _cache.SetStringAsync(key, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) }); return data; }}2. Redis: Powerful Distributed Cache for C#
Redis is an in-memory data store with support for complex structures (lists, sets, hashes). For .NET, the StackExchange.Redis client or the high-level wrapper Microsoft.Extensions.Caching.StackExchangeRedis is used.
Advantages of Redis in C#:
- Speed: sub-millisecond latencies (average 0.5-1 ms).
- Pub/Sub: can notify other services about cache changes.
- Persistence: data can be saved to disk (RDB/AOF).
- Clustering: horizontal scaling out of the box.
Example of advanced usage with JSON serialization:
using StackExchange.Redis;using System.Text.Json;
public class RedisCacheService{ private readonly IDatabase _db; private readonly ConnectionMultiplexer _redis;
public RedisCacheService(string connectionString) { _redis = ConnectionMultiplexer.Connect(connectionString);