Redis缓存用起来88bifa必发娱乐

ABP入门连串目录——学习Abp框架之实操演练
源码路径:Github-LearningMpaAbp


1. 引言

始建职务时我们要求指定分配给哪个人,Demo中我们利用一个下拉列表用来体现当前系统的享有用户,以供用户接纳。大家每创设一个任务时都要去数据库取几回用户列表,然后绑定到用户下拉列表突显。即使就只是对一个demo来说,那样落成也无可厚非,然则在正式项目中,显著是不客观的,浪费程序质量,有待优化。
说到优化,你势必立即就想开了动用缓存。是的,缓存是增高程序质量的飞跃格局之一。
这一节大家就针对这一案例来看一看Abp中哪些接纳缓存来拉长程序品质。

2. Abp的缓存机制

在向来运用缓存从前,我们仍旧来概括梳理下Abp的缓存机制。
Abp之所以能成为一个不错的DDD框架,我想跟小编详细的文档有很大关系,
笔者曾经在ABP官方文档介绍了怎么选取Caching,英文水准好的就直接看官方的吗。

Abp对缓存举办抽象概念了ICache接口,位于Abp.Runtime.Caching取名空间。
并对ICache提供了默许的兑现AbpMemoryCacheAbpMemoryCache是基于MemoryCache.aspx?f=255&MSPPError=-2147217396)的一种落成格局。MemoryCache是微软的一套缓存机制,定义在System.Runtime.Caching取名空间,顾名思义
,在内存中进行高速缓存。我们因此品种爱护图来看下Abp对Cache的落成:

88bifa必发娱乐 1

从图中可以看出主要不外乎多个部分:

  • ICache->CacheBase->AbpMemoryCache:对缓存的抽象以及落到实处;
  • ITypedCache:缓存的泛型落成;
  • ICacheManager->CacheManagerBase->AbpMemoryCacheManager:缓存管理类的虚幻和完成,代码中得以经过注入ICacheManager来获取缓存;
  • ICachingConfiguration->CachingConfiguration:用来安排利用哪类缓存。

3. Abp缓存实操演练

3.1. 恒定优化点

定位到大家的TasksController,其中有二种创制Task的Action,代码如下:

public PartialViewResult RemoteCreate() {
    var userList = _userAppService.GetUsers();
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");
    return PartialView("_CreateTaskPartial");
}

[ChildActionOnly] 
public PartialViewResult Create() {
    var userList = _userAppService.GetUsers();
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");
    return PartialView("_CreateTask");
}

可以看来四个形式都亟待调用_userAppService.GetUsers();来取得用户列表。
现今大家来使用缓存技术对其优化。首先大家应当想到了Asp.net
mvc自带的一套缓存机制,OutputCache。

3.2. 使用[OutputCache]拓展缓存

设若对OutputCache不了然,可以参考我的那篇小说Asp.net mvc
知多少(九)

大家能够不难在Action上添加[OutputCache]特征即可。

[OutputCache(Duration = 1200, VaryByParam = "none")]
[ChildActionOnly] 
public PartialViewResult Create() {
    var userList = _userAppService.GetUsers();
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");
    return PartialView("_CreateTask");
}

[OutputCache(Duration = 1200, VaryByParam = "none")]那句代码的情趣是该action只缓存1200s。1200s后,ASP.NET
MVC会重新执行action并再次缓存。因为是在[ChildActionOnly]中使用[OutputCache],所以该缓存属于Donut
Hole caching。
在该措施内部打个断点,测试唯有首回调用会进入艺术内部,之后1200s内都不会再进来该办法,1200s后会再度进入,表达缓存成功!

3.3. 行使ICacheManager举办缓存

根据上面对Abp缓存机制的梳理,大家得以在急需利用缓存的地点注入ICacheManager来进行缓存管理。
今日大家就在TasksController中流入ICacheManager
表达私有变量,并在构造函数中流入,代码如下:

private readonly ITaskAppService _taskAppService;
private readonly IUserAppService _userAppService;
private readonly ICacheManager _cacheManager;

public TasksController(ITaskAppService taskAppService, IUserAppService userAppService, ICacheManager _cacheManager) {
    _taskAppService = taskAppService;
    _userAppService = userAppService;
    _cacheManager = cacheManager;
}

上边修改RemoteCreateaction如下:

public PartialViewResult RemoteCreate()
{   
    var userList = _cacheManager.GetCache("ControllerCache").Get("AllUsers", 
                          () => _userAppService.GetUsers()) as ListResultDto<UserListDto>;
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");
    return PartialView("_CreateTaskPartial");
}

分析代码发现大家在经过地点代码中拿走的缓存是索要展开类型转换的。原来_cacheManager.GetCache回去的是ICache类型,而ICache定义key-value对应的是string-object品类,所以本来从缓存获取完数据后要拓展类型转换了(注:最新Abp版本为ICache提供了扩张方法,不再须要出示进行类型转换)。那有没有泛型版本?聪明如您,小编对ICache进行打包封装了个ITypedCache以促成项目安全。代码种举办了5种完毕,可以一商讨竟:

public PartialViewResult RemoteCreate()
{
    //1.1 注释该段代码,使用下面缓存的方式
    //var userList = _userAppService.GetUsers();

    //1.2 同步调用异步解决方案(最新Abp创建的模板项目已经去掉该同步方法,所以可以通过下面这种方式获取用户列表)
    //var userList = AsyncHelper.RunSync(() => _userAppService.GetUsersAsync());

    //1.3 缓存版本
    var userList = _cacheManager.GetCache("ControllerCache").Get("AllUsers", () => _userAppService.GetUsers());

    //1.4 转换为泛型版本
    //var userList = _cacheManager.GetCache("ControllerCache").AsTyped<string, ListResultDto<UserListDto>>().Get("AllUsers", () => _userAppService.GetUsers());

    //1.5 泛型缓存版本
    //var userList = _cacheManager.GetCache<string, ListResultDto<UserListDto>>("ControllerCache").Get("AllUsers", () => _userAppService.GetUsers());

    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");
    return PartialView("_CreateTaskPartial");
}

经测试,用户列表正确缓存。

88bifa必发娱乐 2

与[OutputCache]相比较,我们很当然就会问Abp提供的缓存怎么没有配置缓存过期时间,你想到的框架肯定也想到了,Abp的默许缓存过期时间是60mins,大家得以经过在应用缓存项目标Module(模块)中自定义缓存时间。
因为我们是在Web项目中动用的Cache,所以一定到XxxWebModule.cs,在PreInitialize艺术中展开缓存配置。

//配置所有Cache的默认过期时间为2小时
Configuration.Caching.ConfigureAll(cache =>
{
    cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2);
});

//配置指定的Cache过期时间为10分钟
Configuration.Caching.Configure("ControllerCache", cache =>
{
    cache.DefaultSlidingExpireTime = TimeSpan.FromMinutes(10);
});

3.4. 使用IEntityCache对实业举办缓存

3.4.1. 缓存格局的思想

上边的二种缓存方式,我们一般用来存储自定义缓存,但有一个局限性,受到具体缓存过期时间的限制。
沉凝一下,大家缓存的用户列表,它是一个实时会扭转的聚众,而那么些实时是非常危险时的,可能1mins之内就有新用户注册,也有可能几天没有用户注册(比如大家以此Demo),那几个时候就不佳设置缓存过期(刷新)时间。
但由于大家是Demo性质只是为了演示用法,所以大家设定缓存过期日子为10mins也无可厚非。

这有没有一种缓存机制,不必要设置缓存过期时刻,当数码变化的时候就能活动重新缓存呢?
答案是任天由命的,Abp为大家提供了IEntityCache,实体缓存机制。
当大家须求经过ID获取实体数据而又不想常常去数据库查询时,大家就足以行使IEntityCache
换句话说,IEntityCache辅助按实体Id举办动态缓存。

3.4.2. IEntityCache缓存法则

在示范具体操作往日,大家先来教学下IEntityCache的缓存原理:

  • 率先它首先次从数据库中收获实体,然后继续调用将会从缓存获取。
  • 当实体更新或删除时它自动将缓存的实业置为无效状态,因而它将会再下四遍呼吁中从数据库中另行得到。
  • 它利用缓存的类的完好类名作为缓存名称,可以透过为构造函数传参来修改缓存名称。
  • 它是线程安全的。
  • 它利用IObjectMapper将实体映射到缓存项。
    IObjectMapper由AutoMapper模块达成。所以,若是你使用它,你须要AutoMapper模块。您可以覆盖MapToCacheItem方法以手动将实体映射到缓存项。

3.4.3. IEntityCache上手实战

既是是缓存实体,基于大家这几个demo,大家就拿Task实体玩一下吗。
在那里大家先要复习下何以是DTO,重申下DDD为何引入DTO。
Data Transfer Objects(DTO)用来在应用层和突显层之间传输数据。

DTO的要求性:

  1. 天地层的虚幻
  2. 数码隐藏
  3. 种类化和延期加载难点

那这么些DTO跟要讲的实业缓存有何样关系吧?
不绕弯子了,就是说实体缓存不应直接对Entity举行缓存,以幸免缓存时连串化了不应该种类化的目的和实业。
那现实怎么操作呢?大家就平昔上Demo吧。
我们定义一个TaskCacheItem,用来缓存Title、Description、State。并定义映射规则[AutoMapFrom(typeof(Task))]

namespace LearningMpaAbp.Tasks.Dtos
{
    [AutoMapFrom(typeof(Task))]
    public class TaskCacheItem
    {
        public string Title { get; set; }

        public string Description { get; set; }

        public TaskState State { get; set; }
    }
}

下边大家定义一个对准TaskCacheItem的缓存接口。

namespace LearningMpaAbp.Tasks
{
    public interface ITaskCache:IEntityCache<TaskCacheItem>
    {
    }
}

实现ITaskCache缓存接口:

namespace LearningMpaAbp.Tasks
{
    public class TaskCache : EntityCache<Task, TaskCacheItem>, ITaskCache, ISingletonDependency
    {
        public TaskCache(ICacheManager cacheManager, IRepository<Task, int> repository, string cacheName = null) 
            : base(cacheManager, repository, cacheName)
        {
        }
    }
}

现在,当大家须求按照TaskId获取Title、Description、State,大家就足以透过在要求的类中流入注入ITaskCache,来从缓存中赢得。
上面大家在ITaskAppService中添加一个接口TaskCacheItem GetTaskFromCacheById(int taskId);
然后在TaskAppService中落实它,表明变量并在构造函数注入ITaskCache,完毕定义的接口:

private readonly ITaskCache _taskCache;

/// <summary>
///     In constructor, we can get needed classes/interfaces.
///     They are sent here by dependency injection system automatically.
/// </summary>
public TaskAppService(IRepository<Task> taskRepository, IRepository<User, long> userRepository,
    ISmtpEmailSenderConfiguration smtpEmialSenderConfigtion, INotificationPublisher notificationPublisher, ITaskCache taskCache)
{
    _taskRepository = taskRepository;
    _userRepository = userRepository;
    _smtpEmialSenderConfig = smtpEmialSenderConfigtion;
    _notificationPublisher = notificationPublisher;
    _taskCache = taskCache;
}

public TaskCacheItem GetTaskFromCacheById(int taskId)
{
    return _taskCache[taskId];
}

测试如下,直接在马上窗口调用方法,发现只有一条Sql查询生成,表明实体缓存成功。

88bifa必发娱乐 3

想必读到这里,你也许会问,说好的『Redis缓存用起来』,你讲了半天,跟Redis没有半毛钱关系啊。

Redis这么狠心的技巧,当然要压轴出场啊,下边Redis开讲。

4. Redis是怎么样玩意儿

Redis
是一个开源(BSD许可)的,内存中的数据结构存储系统,它能够用作数据库、缓存和音信中间件。它支持八体系型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序聚集(sorted
sets)与限定查询、bitmaps、hyperloglogs和地理空间(geospatial)索引半径查询。

官方的解释就是那样隐晦,对于初识Redis,我们得以省略把它知道为按照内存的进程非凡快品质非凡棒的Key-Value数据库。

有少数内需证实,Redis官方仅帮衬Linux系统不帮衬Windows系统。
而是呢,微软大法好啊,微软开源技术团队(Microsoft Open Tech
group)开发和维护了一个Win64
的版本,大家可以在https://github.com/MSOpenTech/redis左右载Win64版本来玩一玩。

想询问越来越多,请参见汉语官方文档英文官方文档

5. 下手试玩Redis

5.1. 安装Redis

开拓微软开源技术团队维护的Redis
Github链接,找到Releases目录,下载最新版本的msi安装即可。

88bifa必发娱乐 4

下载后,一贯下一步安装即可。

5.2. 简单试玩

找到安装目录,打开cmd并进入到安装目录,输入redis-server redis.windows.conf,即可启动Redis
服务。Redis服务默许启动在6379端口。

88bifa必发娱乐 5

再开行一个cmd窗口,执行redis-cli.exe即可开一个Redis客户端。
执行set命令举行缓存设置;
88bifa必发娱乐,执行get一声令下进行缓存读取;
执行subscribe指令举办频道监听;
执行publish命令向指定频道公布新闻;
具体步骤详参下图:

88bifa必发娱乐 6

6. ABP上试玩Redis缓存

跟着我的脚步,对Redis也算有了中央的认识,我们下边就进来先天的压轴主题,介绍Abp下何以运用redis进行缓存。
先是大家要通晓为何要用Redis举行缓存。
默许的缓存管理是在内存中(in-memory)举行缓存。当您有持续一个并发web服务器要求周转同一个应用程序,默许的缓存管理就不知足你的要求。你或许必要一个分布式/要旨缓存服务器来举行缓存管理,那时Redis就可以登台了。

6.1. Abp集成Redis

率先打开Web层,下载Abp.RedisCache Nuget包安装。
修改XxxWebModule.cs,在DependsOn特性上添加对AbpRedisCacheModule的依赖,并在模块的PreInitialize办法中调用UseRedis壮大方法,代码如下:

[DependsOn(
        typeof(LearningMpaAbpDataModule),
        typeof(LearningMpaAbpApplicationModule),
        typeof(LearningMpaAbpWebApiModule),
        typeof(AbpWebSignalRModule),
        //typeof(AbpHangfireModule), - ENABLE TO USE HANGFIRE INSTEAD OF DEFAULT JOB MANAGER
        typeof(AbpWebMvcModule),
        typeof(AbpRedisCacheModule))]
    public class LearningMpaAbpWebModule : AbpModule
    {
        public override void PreInitialize()
        {
            //省略其他配置代码

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

            //配置所有Cache的默认过期时间为2小时
            Configuration.Caching.ConfigureAll(cache =>
            {
                cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2);
            });

            //配置指定的Cache过期时间为10分钟
            Configuration.Caching.Configure("ControllerCache", cache =>
            {
                cache.DefaultSlidingExpireTime = TimeSpan.FromMinutes(10);
            });            
        }
  ....
}

最后一步在Web.Config文件的【connectionStrings】节点为Abp.Redis.Cache丰盛连接字符串,如下:

  <connectionStrings>
    <add name="Default" connectionString="Server=.\sqlexpress; Database=LearningMpaAbp; Trusted_Connection=True;" providerName="System.Data.SqlClient" />
    <add name="Abp.Redis.Cache" connectionString="localhost"/>
  </connectionStrings>

启动Redis
Server后,F5运行web项目,断点调试,发现已经成功使用Redis缓存。
若未启动Redis
Server,会报Error:It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. SocketFailure on PING

88bifa必发娱乐 7

诸如此类我们就用Redis取而代之了默许的MemoryCache缓存方案,而不须要转移别的代码,Abp就是那般简单、灵活、松藕合!

7. 总结

这篇小说中至关首要梳理了Abp中如何开展缓存管理,并简短介绍了Abp中的缓存机制,并与Asp.net
mvc自带的[Outputcache]缓存举行简短相比,并开展了缓存管理实战演练。最终对Redis举办了概括介绍,并介绍了什么切换Redis缓存。

相关文章