High-Performance .NET Distributed Second-Level Cache Framework
L2Cache is a modern distributed second-level cache library designed for .NET applications. It seamlessly blends local in-memory cache (L1) and Redis distributed cache (L2) to provide lightning-fast response capabilities and ultimate system reliability for high-concurrency applications.
-
🚀 Multi-Level Caching Architecture
- L1 (Memory): Based on
IMemoryCache, providing nanosecond-level data access and automatically handling hot data. - L2 (Redis): Based on
StackExchange.Redis, providing distributed sharing capabilities to ensure data consistency and persistence. - Pub/Sub Real-time Sync: Uses Redis Pub/Sub mechanism to notify all nodes to clear corresponding L1 cache when L2 cache updates, ensuring strong cluster data consistency.
- L1 (Memory): Based on
-
⚡ High-Performance Operations
- Batch Operations: Supports batch APIs like
BatchGet,BatchPut,BatchEvict. Uses Pipeline to reduce network RTT and significantly improve throughput. - Serialization Extensions: Supports System.Text.Json (default) and MemoryPack for efficient binary serialization.
- Batch Operations: Supports batch APIs like
-
🛡️ High Availability & Fault Tolerance
- Fault Degradation: Automatically degrades to pure memory mode when Redis is unavailable, ensuring uninterrupted service.
- Auto Reconnection: Built-in resilient Redis disconnection and reconnection mechanism.
- Stampede Protection: Supports background asynchronous refresh and cache preheating to avoid cache breakdown under high concurrency.
- Concurrency Control: Built-in memory locks (SemaphoreSlim) and distributed locks (Redis Lock) effectively prevent cache stampede and concurrent write conflicts.
-
📊 Full-Link Observability
- Metrics: Based on OpenTelemetry standards, out-of-the-box Prometheus/Grafana monitoring metrics.
- Tracing: Complete distributed tracing support to clearly gain insight into cache hits and penetration paths.
- Logging: Structured cache operation logs.
- HealthCheck: Integrated ASP.NET Core health check to monitor cache component status in real-time.
-
🔌 Flexible & Easy to Use
- Out of the Box: Simple API design, reasonable default configurations, ready to use with just a few lines of code.
- Cache Aside: Recommended to use the
L2CacheServicebase class, which automatically handles "cache miss backfill" logic. - Pluggable: Supports custom serialization (System.Text.Json, MemoryPack, etc.) and telemetry implementations.
| Document | Description |
|---|---|
| Getting Started | Integrate L2Cache into your project from scratch |
| Configuration Guide | Detailed explanation of all configuration options and parameters |
| API Reference | Detailed description of core interfaces and classes |
| Architecture | Understand the internal design principles of L2Cache |
| Advanced Features | Deep dive into locking mechanisms, concurrency control, and batch operations |
Install the core package via NuGet:
dotnet add package L2CacheInstall extension packages as needed:
# Telemetry & Health Checks (Metrics, Tracing, HealthCheck)
dotnet add package L2Cache.Telemetry
# High-Performance Binary Serialization (MemoryPack)
dotnet add package L2Cache.Serializers.MemoryPackRegister services in Program.cs:
using L2Cache.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddL2Cache(options =>
{
// Enable L1 Memory Cache
options.UseLocalCache = true;
// Enable L2 Redis Cache
options.UseRedis = true;
options.Redis.ConnectionString = builder.Configuration.GetConnectionString("Redis");
// Enable Concurrency Locks (Optional)
options.Lock.EnabledMemoryLock = true;
options.Lock.EnabledDistributedLock = true;
// Enable Pub/Sub Message Subscription (Optional)
options.PubSub.Enabled = true;
})
.AddL2CacheTelemetry(); // Enable TelemetryDefine and use cache service:
public class ProductCacheService : L2CacheService<int, ProductDto>
{
private readonly IProductRepository _repo;
public ProductCacheService(
IServiceProvider sp,
IOptions<L2CacheOptions> opts,
ILogger<L2CacheService<int, ProductDto>> logger,
IProductRepository repo)
: base(sp, opts, logger)
{
_repo = repo;
}
// Define cache name prefix
public override string GetCacheName() => "products";
// Define Key generation rule
public override string BuildCacheKey(int id) => id.ToString();
// Define backfill logic (called when cache miss)
public override async Task<ProductDto?> QueryDataAsync(int id)
{
return await _repo.GetByIdAsync(id);
}
}Issues and Pull Requests are welcome!
This project is licensed under the MIT License.