- InMemory Support
- Integrate into Redis caching
- Fast, concurrent, evicted memory, support big cache
Choose caching provider that you need and install it via Nuget.
Install-Package FastCache.InMemory
Install-Package FastCache.Redis
Install-Package FastCache.MultiSource
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
builder.Services.AddInMemoryCache(); // InMemory
// builder.Services.AddMultiBucketsInMemoryCache(); // Big cache
// builder.Services.AddRedisCache("server=localhost:6379;timeout=5000;MaxMessageSize=1024000;Expire=3600", canGetRedisClient: true) // "Expire=3600" is redis global timeout
// canGetRedisClient = true => get redisClient instance
// var redisClient = serviceProvider.GetService<ICacheClient>();
// UserService.cs
[Cacheable("user-single", "{id}", 60 * 30)] // Cache expires after two seconds
public virtual User Single(string id)
{
return _dbContext.Set<User>().Single(x => x.Id == id);
}
**********************************
***** Method must be virtual *****
**********************************
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(build =>
{
build.RegisterDynamicProxy();
});
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
builder.Services.AddInMemoryCache(); // InMemory
builder.Services.AddMvc().AddControllersAsServices(); // the key point
// UserController.cs
[ApiController]
[Route("/user")]
public class UserController : ControllerBase
{
[Route("/"), HttpGet]
[Cacheable("user-single", "{id}", 60 * 10)]
public virtual User Get(string id)
{
return _userService.Single(id);
}
}
**********************************
***** Method must be "virtual" *****
**********************************
- There are three ways of cache eviction,
LRU
andTTL
andRandom
- Fast. Performance scales on multi-core CPUs.
- The cache consists of many buckets, each with its own lock. This helps scaling the performance on multi-core CPUs, since multiple CPUs may concurrently access distinct buckets.
FastCache.InMemory
automatically evicts old entries when reaching the maximum cache size set on its creation.
builder.Services.AddRedisCache("server=127.0.0.1:6000,127.0.0.1:7000,127.0.0.1:6379;db=3;timeout=7000")
This Redis component supports Redis Cluster, configure any node address,
it will be able to automatically discover other addresses and slot distribution,
and use the correct node when performing read and write operations.
This Redis component does not directly support the Redis sentinel, but supports it in the form of active-standby failover.
// UserService.cs
public class UserService
{
[Cacheable("user-single", "{id}", 2)] // Cache expires after two seconds
public virtual User Single(string id)
{
return _dbContext.Set<User>().Single(x => x.Id == id);
}
}
// UserService.cs
public class UserService
{
[Cacheable("user-single", "{id}", 2)] // Cache expires after two seconds
public virtual User Single(string id)
{
return _dbContext.Set<User>().Single(x => x.Id == id);
}
[Evictable(new[] { "user-single", "other cache name" }, "{id}")]
// [Evictable(new[] { "user" }, "{id}*")] // when {id} is "123", it will match keys starting with user:123 and perform a fuzzy deletion.
public virtual void Delete(string id)
{
// delete logic...
}
}
// UserService.cs
public class UserService
{
[Cacheable("user-single", "{id}")] // cache never expires
public virtual User Single(string id)
{
// Get User logic...
}
[Cacheable("user-single", "{user:id}")]
[Evictable(new[] { "user-single", "other cache name" }, "{user:id}")]
public virtual User Update(User user)
{
// Update logic...
}
}
**********************************************
The Update method will be executed first.
After the method is successfully executed, the setup cache will be invalidated,
and finally the Cacheable operation will be executed.
STEP:
1. When "user:id" = "123"
2. Then Evict cache: "user-single:123"
3. Then After updated will caching: "user-single:123" -> { latest user data }
π This means that the cache will always be kept up to date,
thus triggering queries to the database will be significantly reduced π
**********************************************
// Program.cs
builder.Services.AddMultiSourceCache(
"server=localhost:6379;timeout=5000;MaxMessageSize=1024000;Expire=3600", // redis connectionString
true // can get redis client
);
// UserController.cs
// Target.Redis Target.InMemory
[HttpGet]
[MultiSourceCacheable("MultiSource-single", "{id}", Target.Redis, 60)] // Target.Redis
public virtual async Task<User> Get1(string id)
{
return await _userService.Single(id).Result;
}
[HttpGet]
[MultiSourceCacheable("MultiSource-single", "{id}", Target.InMemory, 60)] // Target.InMemory
public virtual async Task<User> Get2(string id)
{
return await _userService.Single(id).Result;
}
**********************************************
According to business needs, flexibly store the cache in redis or memory
**********************************************
// MemoryCache
public static void AddInMemoryCache(
this IServiceCollection services,
int maxCapacity = 1000000,
MaxMemoryPolicy maxMemoryPolicy = MaxMemoryPolicy.LRU, int cleanUpPercentage = 10
)
{ // ... }
// MulitBucketsMemoryCache
public static void AddMultiBucketsInMemoryCache(
this IServiceCollection services,
uint buckets = 5,
uint maxCapacity = 500000,
MaxMemoryPolicy maxMemoryPolicy = MaxMemoryPolicy.LRU,
int cleanUpPercentage = 10)
{ //... }
Parameter | Type | Default | Require | Explain |
---|---|---|---|---|
buckets |
uint | 5 | false | The number of containers to store the cache, up to 128 |
bucketMaxCapacity |
uint | 1000000 | false | (MemoryCache) Initialize capacity (MulitBucketsMemroyCache) The capacity of each barrel, it is recommended that 500,000 ~ 1,000,000 |
maxMemoryPolicy |
MaxMemoryPolicy | MaxMemoryPolicy.LRU | false | LRU = Least Recently Used , TTL = Time To Live, Or RANDOM |
cleanUpPercentage |
int | 10 | false | After the capacity is removed, the percentage deleted |
// foo:bar:1 -> "item1"
{
"foo": {
"bar": [
"item1",
"qux"
]
}
}
// foo:bar:0:url -> "test.weather.com"
{
"foo": {
"bar": [
{
"url": "test.weather.com",
"key": "DEV1234567"
}
]
}
}