必威体育Betway必威体育官网
当前位置:首页 > IT技术

ABP-缓存

时间:2019-08-12 04:12:09来源:IT技术作者:seo实验室小编阅读:62次「手机版」
 

abp

前言:什么是缓存

缓存就是数据交换的缓冲区(称作cache),当某一方法要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从数据库中找。由于缓存的运行速度比数据库查找速度快得多,故缓存的作用就是帮助系统更快地运行。

图解原理

下面就让我们看看ABP是怎么实现缓存机制的吧

我们实现缓存主要包括4个部分:

  • ICache->CacheBase->AbpMemoryCache:对缓存的抽象以及实现;
  • ITypedCache:缓存的泛型实现;
  • ICacheManager->CacheManagerBase->AbpMemoryCacheManager:缓存管理类的抽象和实现,代码中可以通过注入ICacheManager来获取缓存;
  • ICachingconfiguration->CachingConfiguration:用来配置使用哪种缓存。

一. 使用ICacheMananger实现缓存

1.1:使用

如果使用ICacheMananger缓存,我们只需要通过依赖注入把缓存声明就可以了

 private readonly IRepository<Person, int> _entityRepository; //声明Person存储仓
        private readonly ICacheManager _cacheManager;//依赖注入缓存
        public PersonCacheAPPlicationService(IRepository<Person, int> entityRopository
            , ICacheManager cacheManager)
        {

            _cacheManager = cacheManager;//依赖注入缓存
            _entityRepository = entityRopository;

        }

//在接口中使用

    public async Task<List<Person>> GetAll()
        {

           // var entity = await _entityRepository.GetAllListAsync();
            var entityCache = await _cacheManager.GetCache("PeopelCache") //缓存的唯一表示名
                .Get("Peopel", () => _entityRepository.GetAllListAsync());
            return entityCache;
        }

然后我们怎么监控缓存的使用情况呢?

我们在缓存点加个小断点,监视窗口输入 _cacheManager.GetCache("PeopelCache"),就可以查看到它的缓存信息了

我们可以看到缓存的时间是1个小时(默认的),变化时间是空,名字是PeopelCache

1.2我们了解到,它还有个ITypedCache泛型版本

把代码改为这样便可

  var entityCache =  _cacheManager.GetCache("controllerCache")
                                    .AsTyped<string,List<Person>>()
                                   .Get("AllUsers", () =>  _entityRepository.GetAllList());

1.3了解一下ICache对象。

ICacheManager.GetCache方法返回了一个ICache对象的。

而我们上面用到的是ICache对象的Get方法。ICache接口还有其它方法,例如:GetOrDefault,Set(设置缓存),Remove(移除缓存)和Clear(清除缓存。当然也有这些方法的异步(async)版本。

1.4Configuration设置缓存时间

缓存的过期时间默认是60分钟。它是变化的。如果你在60分钟内没有使用该缓存,该缓存会被自动的移除。如果你想改变所有的缓存或者指定的缓存来的默认过期时间,你可以这样做,实现如下:

在web.Core层 找到  项目名WebCoreModule  下的 PreInitialize()方法 加入

   //配置所有Cache的默认过期时间为2小时
            Configuration.Caching.configureAll(
                cache =>
                {
                    cache.DefaultabsoluteExpireTime = timespan.FromHours(2);
                });
            ////配置指定的Cache过期时间为1天
            Configuration.Caching.Configure(
                "PeopelCache", cache =>
                {
                    cache.DefaultAbsoluteExpireTime = TimeSpan.FromDays(1);
                });

我们可以看到PeopelCache 这个缓存 过期时间改为了一天,变化时间改为了2个小时了

这些配置将会在首次创建缓存的时候生效。配置不仅仅局限于DefaultSlidingExpireTime,你可以利用ICache接口中的属性获取方法来自由的配置并且初始化它们。

二.使用IEntityCache对实体进行缓存

为什么又要学使用IEntityCache缓存呢?

我们可以看到,使用ICacheMananger缓存是有过期时间的,在网上看到一个很好的例子:受到了一个时间的限制我们缓存的用户列表,它是一个实时会变化的集合,而这个实时是不定时的,可能1mins之内就有新用户注册,也有可能几天没有用户注册,这个时候就不好设置缓存过期(刷新)时间。

当我们需要通过ID获取实体数据而又不想经常去数据库查询时,我们就可以使用IEntityCache。

换句话说,IEntityCache支持按实体Id进行动态缓存。

而IEntityCache缓存是,不需要设置缓存过期时间,当数据变化的时候就能自动重新缓存。

可以看到这是我们的实体

  [Table("Person")]
    public class Person : FullauditedEntity
    {
        public string Name { get; set; }
        public int Sex { get; set; }
    }

并且,假设我们通过该实体的Id,需要频繁调用取得Person实体的Name。首先,我们应该创建一个类来存储 cache items

 [AutoMapFrom(typeof(Person))]
  public  class PersonCacheItem
    {
         public string Name { get; set; }
    }

我们 不应该直接存储实体到缓存中 因为缓存的时候需要序列化缓存对象而实体可能不能被序列化(尤其是实体的导航属性)。这就是为什么我们定义了一个简单的像DTO的类来存储数据到缓存中。我们添加了 AutoMapFrom 特性,这是因为我们想使用 AutoMapper 来自动的转换 Person 实体为 PersonCacheItem 对象。如果我们不使用 AutoMapper,那么我们应该重写 EntityCache 类的 MapToCacheItem 方法手动转换/映射它。

定义一个接口为缓存类的接口:

public interface IPersonCache : IEntityCache<PersonCacheItem>
{

}

最后,我们就可以创建缓存类来缓存Person实体:

ItransientDependency:所有实现此接口的类都自动注册到依赖项

IPersonCache:缓存类接口

EntityCache<A,B>:把A的数据缓存到B中

public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency
{
    public PersonCache(ICacheManager cacheManager, IRepository<Person> repository)
        : base(cacheManager, repository)
    {

    }
}

在接口处使用了

  public class PersonCacheApplicationService : AbpDemoAppServiceBase
    {
        private readonly IPersonCache _personCache;
        public PersonCacheApplicationService(IRepository<Person, int> entityRopository
           )
        {   _personCache = personCache;  }
//如果查询为空,会报错,最好加个错误判断
   public string GetPersonNameById(int id)
    {
            try
            {
                return _personCache[id].Name; //alternative: _personCache.Get(id).Name;
            }
            catch {
                return "值为空";  }
   }}

我们整个的思路是

  • 在首次调用的时候我们通过仓储从数据库中取得实体。那么随后的调用都是从缓存中取得。

  • 如果实体被更新或者删除,它会自动的无效实体。因此,它会在下次调用的时候重新从数据库中检索数据。

  • 使用 IObjectMapper 接口来映射实体到缓存项。IObjectMapper 接口在 AutoMapper 中被实现。

  • 使用缓存类缓存Name

三.Redis Cache 集成

如果们不集成Redis Cache,上面的缓存操作是缓存在系统内存的。

然而我们想要集成RedisCahe 只需要在添加一个安装包,一个依赖,一段代码和就完成了

当然了,首先我们得装一个Redis(我就不展开了):https://blog.csdn.net/wangwengrui40/article/details/86599702

一个安装包:下载Abp.RedisCache Nuget包安装。

一个依赖:在:web.Core层 找到  项目名WebCoreModule 的 DependsOn特性上添加对AbpRedisCacheModule的依赖,

一段代码:同样在web.Core层 找到  项目名WebCoreModule  下的 PreInitialize()方法 加入,就可以使用本地的Redis了。

 //配置使用Redis缓存
            Configuration.Caching.UseRedis();

如果我们想陪着外网的Redis,那么只需要改下链接字符串 

password:Redis密码

connectTimeout:连接超时时间,这里设置的是1000毫秒

connectretry:重试连接次数

syncTimeout:同步操作默认超时时间

DatabaseId:选中的数据库

            Configuration.Caching.UseRedis(
                options =>
                       {//服务器地址
options.ConnectionString = "192.168.1.181:6379,Password = 123456,connectTimeout=1000,connectRetry=1,syncTimeout=1000";
                           options.DatabaseId = Convert.ToInt32(_appConfiguration.GetConnectionString("RedisCacheDatabaseId"));
                       });

如果出现以下错误,那就是,Redis服务还没开启 ,或没按照

题外话:

翻了下ABP框架的源码,发现

模板自带的Role、User 等自带了一个 RoleManager的实体缓存接口。实现方式与IEntityCache缓存一样

我们来感受一下他的代码

参考文章:http://www.cnblogs.com/sheng-jie/p/6508241.html

https://blog.csdn.net/WuLex/article/details/78409051

相关阅读

Hibernate 二级缓存和查询缓存

一级缓存:   1,在session上面有一个一级缓存;一级缓存的生命周期和session相同,一级缓存最大生命周期就是一个线程;在web环境下

服务器缓存(Cache)

缓存指的是将需要频繁访问的网络内容存放在离用户较近、访问速度更快的系统中,以提高内容访问速度的一种技术。服务器缓存工作原理

ThinkPHP缓存文件写入失败!:./Runtime/Cache/..

最近在学习ThinkPHP框架,从网上down了一个项目,在本地配置这个项目时,出现了一个问题,无法写入/Runtime/Cache缓存,这个问题是权限问题

Chrome浏览器清除页面js文件缓存的方法

Chrome浏览器清除页面js文件缓存 Chrome浏览器清除js缓存方法虽然简单,但有些人还是不太会,有些人会去设置里面清除有时候没有用,

分布式缓存击穿(布隆过滤器 Bloom Filter)

缓存中无值(未宕机) 互斥锁 缓存永不过期 缓存宕机 白名单 布隆过滤器 代码实现 前面的文章介绍了缓存的分类和使用的场景

分享到:

栏目导航

推荐阅读

热门阅读