缓存管理器


  缓存管理器 ICacheManager 接口提供了读取或设置缓存项的方法,IMemoryCacheManagerIDistributedCacheManager 接口只是为了区分内存缓存和分布式缓存,它们并没有再提供其他的方法。


1、获得实例

  要使用缓存管理器,首先得获取到它的实例。我们不推荐使用 new 构造一个实例,而是使用 CacheManagerFactory 工厂类来创建一个实例。该工厂类提供一个 CreateManager 方法,可以接收一个 configName 参数,这个参数对应缓存配置(可参考 配置与扩展)中配置项的名称,如果未配置缓存配置项,则返回内存缓存管理器的单例。如下所示:

[TestMethod]
public void TestCreateManager()
{
    var manager = CacheManagerFactory.CreateManager();
    Assert.IsNotNull(manager); //MemoryCacheManager
}

  在使用 IOC 的环境中,也可以通过构造注入或属性注入得到 ICacheManager 的实例。如下所示:

public class HomeController : Controller
{
    private readonly ICacheManager _cacheManager;
    
    public HomeController(ICacheManager cacheManager)
    {
        _cacheManager = cacheManager;
    }
}

2、添加缓存项

  Add 方法用于将缓存项添加到管理器中。你可以设置过期时间,也可以设置过期策略(可参考 缓存过期策略)。如下所示:

public class PersonCache
{
    public string Name { get; set; }
}

[TestMethod]
public void TestAdd()
{
    var manager = CacheManagerFactory.CreateManager();
        
    //10分钟之后过期
    manager.Add("testKey1", new PersonCache { Name = "fireasy" }, TimeSpan.FromMinutes(10));
        
    //永不过期
    manager.Add("testKey2", new PersonCache { Name = "fireasy" }, NeverExpired.Instance);
}

[TestMethod]
public async Task TestAddAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    //10分钟之后过期
    await manager.AddAsync("testKey1", new PersonCache { Name = "fireasy" }, TimeSpan.FromMinutes(10));
        
    //永不过期
    await manager.AddAsync("testKey2", new PersonCache { Name = "fireasy" }, NeverExpired.Instance);
}

  另外,Add 方法还有一个 CacheItemRemovedCallback 委托的参数,用于当缓存项过期被移除时通知应用程序。

[TestMethod]
public void TestAddWithRemovedCallback()
{
    var manager = CacheManagerFactory.CreateManager();
        
    //10分钟之后过期
    manager.Add("testKey1", new PersonCache { Name = "fireasy" }, TimeSpan.FromMinutes(10), (key, value) => 
    {
        Console.WriteLine($"{key} 已被移除。");
    });
}

3、判断缓存项是否存在

  Contains 方法用于判断缓存器里有没有指定的 key。如下所示:

[TestMethod]
public void TestContains()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsTrue(manager.Contains("testKey1"));
}

[TestMethod]
public async Task TestContainsAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsTrue(await manager.ContainsAsync("testKey1"));
}

4、获取缓存项

  Get 方法用于获取指定 key 的缓存项。如下所示:

[TestMethod]
public void TestGet()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(manager.Get("testKey1"));
    Assert.IsNotNull(manager.Get<PersonCache>("testKey1"));
}

[TestMethod]
public async Task TestGetAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(await manager.GetAsync("testKey1"));
    Assert.IsNotNull(await manager.GetAsync<PersonCache>("testKey1"));
}

5、尝试获取缓存项

  TryGet 方法用于获取指定 key 的缓存项,如果缓存项不存在,则使用 valueCreator 委托将数据添加到管理器,缓存依赖项也是通过一个委托创建。如下所示:

[TestMethod]
public void TestTryGet()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(manager.TryGet("testKey8", () => new PersonCache { Name = "fireasy" }));
}

[TestMethod]
public async Task TestTryGetAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(await manager.TryGetAsync("testKey8", () => new PersonCache { Name = "fireasy" }));
}

  TryGet 方法还有一个 out 的重载,它不会使用委托创建缓存项,它会回一个 bool 值。如下所示:

[TestMethod]
public void TestTryGet()
{
    var manager = CacheManagerFactory.CreateManager();
        
    if (manager.TryGet("testKey1", out PersonCache item))
    {
        Console.WriteLine(item.Name);
    }
}

[TestMethod]
public async Task TestTryGetAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    if (await manager.TryGetAsync("testKey1", out PersonCache item))
    {
        Console.WriteLine(item.Name);
    }
}

6、获取所有key

  GetKeys 方法用于获取所有的 key。pattern 参数是一个通配符,可以使用 *? 这样的字符。如下所示:

[TestMethod]
public void TestGetKeys()
{
    var manager = CacheManagerFactory.CreateManager();
        
    manager.GetKeys("*")
}

[TestMethod]
public async Task TestGetKeysAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    await manager.GetKeysAsync("*")
}

7、移除缓存项

  Remove 方法用于移除指定 key 的缓存项。如下所示:

[TestMethod]
public void TestRemove()
{
    var manager = CacheManagerFactory.CreateManager();
        
    manager.Remove("testKey1")
}

[TestMethod]
public async Task TestRemoveAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    await manager.RemoveAsync("testKey1")
}

8、清空所有缓存项

  Clear 方法用于清空所有的缓存项。如下所示:

[TestMethod]
public void TestClear()
{
    var manager = CacheManagerFactory.CreateManager();
        
    manager.Clear();
}

[TestMethod]
public async Task TestClearAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    await manager.ClearAsync();
}

9、获取缓存的有效时间

  GetExpirationTime 方法用于获取指定 key 的缓存项的有效时间(TimeSpan)。如下所示:

[TestMethod]
public void TestGetExpirationTime()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(manager.GetExpirationTime("testKey1"));
}

[TestMethod]
public async Task TestGetExpirationTimeAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    Assert.IsNotNull(await manager.GetExpirationTimeAsync("testKey1"));
}

10、设置缓存的有效时间

  SetExpirationTime 方法用于设置指定 key 的缓存项的有效时间。如下所示:

[TestMethod]
public void TestSetExpirationTime()
{
    var manager = CacheManagerFactory.CreateManager();
        
    manager.SetExpirationTime("testKey1", () => new RelativeTime(TimeSpan.FromMinutes(10)));
}

[TestMethod]
public async Task TestSetExpirationTimeAsync()
{
    var manager = CacheManagerFactory.CreateManager();
        
    await manager.SetExpirationTimeAsync("testKey1", () => new RelativeTime(TimeSpan.FromMinutes(10)));
}

11、哈希集

  GetHashSet 方法可以获取一个哈希子集,它是一个 ICacheHashSet<TKey, TValue> 接口,提供的方法与 ICacheManager 接口相类似。如下所示:

[TestMethod]
public void TestHashSet()
{
    var manager = CacheManagerFactory.CreateManager();
        
    var hashSet = manager.GetHashSet<string, PersonCache>("personSet");
    var person = hastGet.TryGet("01", () => new PersonCache { Name = "fireasy" });
    Assert.IsNotNull(person);
}

  GetHashSet 方法的 initializeSet 参数是一个委托,在初始创建 key 的时候,由该委托生成一个集合用于初始化哈希集。如下所示:

[TestMethod]
public void TestInitializeHashSet()
{
    var manager = CacheManagerFactory.CreateManager();
        
    var hashSet = manager.GetHashSet<string, PersonCache>("personSet", () => 
    {
        return new [] 
        {
            Tuple.Create("01", new PersonCache { Name = "fireasy01" }, NeverExpired.Instance),
            Tuple.Create("02", new PersonCache { Name = "fireasy02" }, NeverExpired.Instance),
            Tuple.Create("03", new PersonCache { Name = "fireasy03" }, NeverExpired.Instance),
            Tuple.Create("04", new PersonCache { Name = "fireasy04" }, NeverExpired.Instance)
        };
    });
        
    if (hashSet.TryGet("01", out PersonCache person))
    {
        Assert.AreEqual("fireasy01", person.Name);
    }
}

12、增强功能

  IEnhancedCacheManager 接口定义了用于获取增量和减量,以及事务的方法。

  • TryIncrement 方法

  表示获得一个递增的值,valueCreator 委托用于设置初始值,setp 表示步长。

  • TryDecrement 方法

  表示获得一个递减的值,valueCreator 委托用于设置初始值,setp 表示步长。

  • UseTransaction 方法

  用于开启一个事务,用于锁住一个操作,分布式锁就是这样的应用。