ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十五节--缓存小结与ABP框架项目中 Redis

ABP+AdminLTE+Bootstrap Table权限管理系统一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMShtml

为何要用缓存

为何要用缓存呢,说缓存以前先说使用缓存的优势。git

  • 减小寄宿服务器的往返调用(round-trips)。
  • 若是缓存在客户端或是代理,将减小对服务器的请求,减小带宽。
  • 减小对数据库服务器的往返调用(round-trips)。
  • 当内容缓存在web服务器,可以减轻对数据库的请求。
  • 减小网络带宽。
  • 避免了从新生成可重用内容的时耗。
  • 提升性能
  • 由于缓存减小了round-trips, network traffic(网络带宽),并避免- 了生成可重用内容的时耗,因此对性能有巨大的提升。

传统的缓存方式

传统的缓存方式以下面这张图 github

image.png
以前咱们处理方式处理起来也很简单

  1. 页面输出缓存,直接在 ASP.NET中页面缓存的使用OutputCache 在aspx页的顶部加这样一句便可: <%@ OutputCache Duration="60" VaryByParam="none" %> Duration 表示缓存的时间秒,必选,不然报错。
  2. 第二种方式 if (this.Cache["Keys"] == null) { this.Cache.Insert("Keys", List, null, DateTime.Now.AddHours(2), TimeSpan.Zero); }

这里是检查缓存中Keys是否存在,若是不存在,则写入一个新的值List.还有其余的一些使用方法。 web

image.png

上面两种方式显然不在如今使用范畴,也不在我想说的范畴以内。,年代貌似有点久远,不用webform基本用不到。如今咱们更可能是的使用MVC。 咱们想说的是MVC输出缓存。redis

MVC缓存

输出缓存Outputcache ,分为Action输出缓存和Controller输出缓存。使用的场景包括某个页面的数据更新不是很频繁,不须要每次都从数据库区查询。缓存起来从内存中读取。数据库

数据缓存:是相对于全局的。任何地方须要调用的时候均可以去调用。使用的场景包括权限管理这种模块的。每一个角色对于菜单的访问都是固定的,因此有必要将角色,权限,菜单这种数据作一个全局的数据缓存。修改时再作缓存的更新。windows

输出缓存和数据缓存区别:打个比方输出缓存就像是“局部变量”,数据缓存就像是全局变量(只是个比喻)。缓存

Controller输出缓存和 Action缓存使用方式是同样的,就是Controller 或Action上打[OutPutCache]特性标签。可是他们之间又是有区别的。安全

1、控制器缓存服务器

Control缓存的做用域是整个控制器,因此在这个控制器下的全部Action都会被缓存起来。Control缓存的粒度比较粗,应用也比较少些。 [OutputCache(Duration = 10)] public class HomeController : Controller { public ActionResult Index() { ViewBag.CurrentTime = DateTime.Now; return View(); } } 2、Action缓存 将[OutPutCache]特性标签打在Action上,这样,只有加缓存的Action才会有缓存,其余的Action是没有的。

Outputcache特性经常使用的属性参数

名称 描述
AllowMultiple 获取或设置一个值,该值指示是否可指定筛选器特性的多个实例。
CacheProfile 获取或设置缓存配置文件名称。
ChildActionCache 获取或设置子操做缓存。
Duration 获取或设置缓存持续时间(以秒为单位)。
Location 获取或设置位置。
NoStore 获取或设置一个值,该值指示是否存储缓存。
Order 获取或者设置执行操做筛选器的顺序。
SqlDependency 获取或设置 SQL 依赖项。
TypeId (从Attribute继承。)
VaryByContentEncoding 获取或设置基于内容变化的编码。
VaryByCustom 获取或设置基于自定义项变化的值。
VaryByHeader 获取或设置基于标头变化的值。
VaryByParam 获取或设置基于参数变化的值。

输出缓存CacheProfile使用配置文件设置缓存

举例其中的CacheProfile,这种方式便于统一配置,固然也能够设置参数duration、location 、varybyparam等。咱们须要在system.web 节点下加入这些

`






其实做用和效果仍是同样,无非就是方便点,统一的配置参数都直接写webconfig文件里面。其实也能够Controller中写。 配置好了以后咱们直接在控制器调用相应的名字的OutputCache特性标签便可。 [OutputCache(CacheProfile= "TestConfigCache")] public ActionResult Index() { ViewBag.CurrentTime = DateTime.Now; return View(); } ` 更多的方式,须要下去再研究下。

ABP中使用ICacheManager进行缓存管理

ABP中有两种cache的实现方式:MemroyCacheRedisCache,二者都继承至ICache接口(准确说是CacheBase抽象类)。ABP核心模块封装了MemroyCache来实现ABP中的默认缓存功能。 Abp.RedisCache这个模块封装RedisCache来实现缓存(经过StackExchange.Redis这个类库访问redis)。

ABP给出了一个抽象缓存基类。并在内部使用了该抽象基类。使用 MemoryCache 来实现了该抽象基类。它可以被任何其它的缓存类来扩展。Abp.RedisCache 包就扩展了该缓存基类。 ABP对外提供了一个缓存接口ICacheMananger。咱们经过构造函数注入这个接口来获取缓存。示例以下:

image.png

在这个示例中,咱们注入了 ICacheManager接口,s而且获取了一个名称为ControllerCache的缓存。首先咱们先对ControllerCache进行清除,而后存入缓存,缓存的名字是大小写敏感的,那就是"ControllerCache"和"CONTROLLERCACHE"取得的缓存内容是不一样的。

注意:GetCache方法 千万不要在你的构造函数中使用GetCache方法。若是类不是一个单例对象那么该缓存可能会被dispose掉。

ICache

ICacheManager.GetCache方法返回了一个ICache对象。每个缓存都是基于名称单例存在的。只有首次访问时才会被建立,之后你每次用相同的名称去获取的缓存都是相同的。因此咱们能够在不一样的类中使用相同的名称来共享相同的缓存。

在示例代码中,咱们简单的使用了ICache.Get方法,它有两个参数:

  • key : 要获取的缓存项的惟一标识符
  • factory:若是根据给定的key获取到的缓存项为空,那么factory将会建立一个标识符为key的缓存,而且返回该缓存

ICache接口还有其它方法,如前面Clear(),Get(),GetOrDefaultSetRemoveClear。固然也有这些方法的异步(async)版本。以下图,我就懒得写了。

image.png

ITypedCache

ICache 接口用key(字符串类型)来获取缓存value(object类型)。ITypedCacheICahe提供了一个 类型安全 的包装;为了使类型安全转换(ICacheITypedCache),咱们能够用扩展方法 AsTyped,而不须要写其它强制类型转换的代码,以下所示: ITypedCache<int, Item> myCache = _cacheManager.GetCache("MyCache").AsTyped<int, Item>();

Configuration

缓存的过时时间默认是60分钟。它是变化的。若是你在60分钟内没有使用该缓存,该缓存会被自动的移除。若是你想改变全部的缓存或者指定的缓存来的默认过时时间,你能够这样作,实现以下: //对全部缓存的配置 Configuration.Caching.ConfigureAll(cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2); }); //对指定缓存的配置 Configuration.Caching.Configure("MyCache", cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(8); });

这段代码你应该放在模块(module)的 PreInitialize 方法中。如上所示:MyCache将会在8小时后过时,而其余的缓存将在2小时后过时。

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

Entity Caching

ABP的缓存系统是以通用为目的,它有一个 EntityCache 基类,若是你须要的话,这个基类能够帮助你缓存实体。使用这个基类,咱们能够经过ID取得实体,而且咱们经过ID来缓存实体,这样之后就不须要频繁的查询数据库去取得实体。假设咱们有个Person实体,像下面同样: public class Person : Entity { public string Name { get; set; } public int Age { 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实体: public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency { public PersonCache(ICacheManager cacheManager, IRepository<Person> repository) : base(cacheManager, repository) { } }

这样就OK了,咱们的person缓存已经准备好可使用了。缓存类可使瞬时(如同这个例子)或者是单例。这不是说缓存数据是瞬态的。在你的应用程序中它一直是全局缓存而且是线程安全的。

如今,不管在什么地方咱们须要取得Person的Name,咱们能够经过Person的Id从缓存中取得它。以下所示: public class MyPersonService : ITransientDependency { private readonly IPersonCache _personCache; public MyPersonService(IPersonCache personCache) { _personCache = personCache; } public string GetPersonNameById(int id) { return _personCache[id].Name; //alternative: _personCache.Get(id).Name; } } 咱们很容易的注入 IPersonCache 接口,经过该接口取得缓存项和Name属性。

那么EntityCache是怎么工做的?

  • 在首次调用的时候咱们经过仓储从数据库中取得实体。那么随后的调用都是从缓存中取得。
  • 若是实体被更新或者删除,它会自动的无效实体。所以,它会在下次调用的时候从新从数据库中检索数据。
  • 使用 IObjectMapper 接口来映射实体到缓存项。IObjectMapper 接口在 AutoMapper 中被实现。因此,若是你使用了自动映射,那么就须要 AutoMapper模块。你能够重写 MapToCacheItem 方法手动映射它到缓存项。
  • 使用缓存类的FullName做为缓存的Name,你能够经过传入的缓存名到基类的构造函数来改变它。
  • 它是线程安全的。 若是你有更复杂的缓存需求,那么你须要扩展 EntityCache 类或者建立你本身的解决方案。

Redis Cache 集成

Redis是什么,Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它能够用做数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)与范围查询、bitmaps、hyperloglogs和地理空间(geospatial)索引半径查询。 Redis 是彻底开源免费的,遵照BSD协议,是一个高性能的key-value数据库。 Redis 与其余 key - value 缓存产品有如下三个特色

  • Redis支持数据的持久化,能够将内存中的数据保存在磁盘中,重启的时候能够再次加载进行使用。
  • Redis不只仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。 Redis 优点
  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操做。
  • 原子 – Redis的全部操做都是原子性的,意思就是要么成功执行要么失败彻底不执行。单个操做是原子性的。多个操做也支持事务,即原子性,经过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过时等等特性。
  • 多实用工具 - Redis是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis本地支持发布/订阅),应用程序中的任何短时间数据,例如,web应用程序中的会话,网页命中计数等。

(1)首先,咱们前往github.com/dmajkic/red…下载安装包,直接下一步下一步就能够了。 而后打开安装的地址就能够看到以下的文件:

image.png
(2) 而后启动Redis服务,咱们cmd到安装目录下,而后输入命令 redis-server.exe redis.windows.conf 就会看到下面的画面证实咱们启动服务成功。
image.png
abp默认Cache Mananger是使用 in-memory来缓存。因此,这可能会成为一个问题,若是有多个并发的Web服务运行在同一个应用中。在这种状况下,你可能想要一个分布式/中央缓存服务器。那么,你可使用Redis来做为你的缓存服务。 首先,你须要安装 Abp.RedisCachenuget package 到你的项目中(你能够安装它到你的Web项目)。这里我遇到一个错误。
image.png
开始的时候我搞了半天不知道为何会出现这个莫名其妙的错误,后来才发现,原来我引入Abp.RedisCache版本和abp版本不一致。才致使的这个错误,好比你abp是3.1.1,那么你的Abp.RedisCache最好也是对应的版本,最好的话把abp和Abp.RedisCache都升级到最新版本,就不会有错误了。 而后咱们看看Abp.Runtime.Caching.Redis;依赖项以及之间的关系。
image.png
而后在ABPCMSWebModule配置一下。
image.png
ABPCMSApplicationModule中引入。
image.png
Web.config中配置
image.png
你也能够添加配置到appSettings来设置Redis数据库的Id。如: <add key="Abp.Redis.Cache.DatabaseId" value="2"/> 在同一个服务器上使用不一样的数据库Id是很是有用的这能够建立不一样的Key Spaces(隔离缓存)。 UseRedis有一个重载方法,你能够经过这个方法来传入配置参数,这能够覆盖掉配置文件中的配置。关于Redis的其余配置能够查看 Redis文档

在下面UserList打下断点调试进去。

image.png
看到效果以下图,证实咱们AbpRedisCache引入成功。
image.png
固然为了更好的进行可视化操做,我建议使用跨平台开源Redis DB管理工具(Redis Desktop Manager)地址: redisdesktop.com/download 下载下来直接下一步下一步安装便可。
image.png
而后运行项目,而后咱们在看下Redis Desktop Manager工具,效果以下图:
image.png
使用可视化工具很方便

  1. 新建链接,输入redis主机host,端口号port,再起个生动形象,简明达意的别名。
  2. 该工具支持根据筛选条件查询key,add new key,reload等。
  3. 支持经常使用redis操做,针对目标key执行rename,delete,addrow,reload value操做。
  4. 命令控制台操做 !你们感兴趣能够本身玩一下。 另外关于实体修改后自动更新缓存的实现远离能够参考 www.cnblogs.com/loyldg/p/us… 这个文章。

Github项目地址:github.com/Jimmey-Jian…

ABP+AdminLTE+Bootstrap Table权限管理系统一期 [Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS](https://github.com/Jimmey-Jiang/ABP-

相关文章
相关标签/搜索