返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期
緩存
為什么要用緩存
為什么要用緩存呢,說緩存之前先說使用緩存的優點。
- 減少寄宿服務器的往返調用(round-trips)。
- 如果緩存在客戶端或是代理,將減少對服務器的請求,減少帶寬。
- 減少對數據庫服務器的往返調用(round-trips)。
- 當內容緩存在web服務器,能夠減輕對數據庫的請求。
- 減少網絡帶寬。
- 避免了重新生成可重用內容的時耗。
- 提高性能
- 因為緩存減少了round-trips, network traffic(網絡帶寬),並避免- 了生成可重用內容的時耗,所以對性能有巨大的提高。
傳統的緩存方式
傳統的緩存方式如下面這張圖
之前我們處理方式處理起來也很簡單
- 頁面輸出緩存,直接在 ASP.NET中頁面緩存的使用OutputCache 在aspx頁的頂部加這樣一句即可:
<%@ OutputCache Duration="60" VaryByParam="none" %>
Duration 表示緩存的時間秒,必選,否則報錯。 - 第二種方式
if (this.Cache["Keys"] == null) { this.Cache.Insert("Keys", List, null, DateTime.Now.AddHours(2), TimeSpan.Zero); }
這里是檢查緩存中Keys是否存在,如果不存在,則寫入一個新的值List.還有其他的一些使用方法。
上面兩種方式顯然不在現在使用范疇,也不在我想說的范疇之內。,年代貌似有點久遠,不用webform基本用不到。現在我們更多是的使用MVC。
我們想說的是MVC輸出緩存。
MVC緩存
輸出緩存:Outputcache
,分為Action輸出緩存和Controller輸出緩存。使用的場景包括某個頁面的數據更新不是很頻繁,不需要每次都從數據庫區查詢。緩存起來從內存中讀取。
數據緩存:是相對於全局的。任何地方需要調用的時候都可以去調用。使用的場景包括權限管理這種模塊的。每個角色對於菜單的訪問都是固定的,所以有必要將角色,權限,菜單這種數據做一個全局的數據緩存。修改時再做緩存的更新。
輸出緩存和數據緩存區別:打個比方輸出緩存就像是“局部變量”,數據緩存就像是全局變量(只是個比喻)。
Controller輸出緩存和 Action緩存使用方式是一樣的,就是Controller 或Action上打[OutPutCache]特性標簽。但是他們之間又是有區別的。
一、控制器緩存
Control緩存的作用域是整個控制器,所以在這個控制器下的所有Action都會被緩存起來。Control緩存的粒度比較粗,應用也比較少些。
[OutputCache(Duration = 10)] public class HomeController : Controller { public ActionResult Index() { ViewBag.CurrentTime = DateTime.Now; return View(); } }
二、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 Redis Cache
ABP中使用ICacheManager進行緩存管理
ABP中有兩種cache的實現方式:MemroyCache
和 RedisCache
,兩者都繼承至ICache接口(准確說是CacheBase
抽象類)。ABP核心模塊封裝了MemroyCache
來實現ABP中的默認緩存功能。 Abp.RedisCache
這個模塊封裝RedisCache
來實現緩存(通過StackExchange.Redis
這個類庫訪問redis)。
ABP給出了一個抽象緩存基類。並在內部使用了該抽象基類。使用 MemoryCache 來實現了該抽象基類。它能夠被任何其它的緩存類來擴展。Abp.RedisCache 包就擴展了該緩存基類。
ABP對外提供了一個緩存接口ICacheMananger。我們通過構造函數注入這個接口來獲取緩存。示例如下:
在這個示例中,我們注入了 ICacheManager接口,s並且獲取了一個名稱為ControllerCache的緩存。首先我們先對ControllerCache進行清除,然后存入緩存,緩存的名字是大小寫敏感的,那就是"ControllerCache"和"CONTROLLERCACHE"取得的緩存內容是不同的。
注意:GetCache方法 千萬不要在你的構造函數中使用GetCache方法。如果類不是一個單例對象那么該緩存可能會被dispose掉。
ICache
ICacheManager.GetCache
方法返回了一個ICache
對象。每一個緩存都是基於名稱單例存在的。只有首次訪問時才會被創建,以后你每次用相同的名稱去獲取的緩存都是相同的。所以我們可以在不同的類中使用相同的名稱來共享相同的緩存。
在示例代碼中,我們簡單的使用了ICache.Get
方法,它有兩個參數:
- key : 要獲取的緩存項的唯一標識符
- factory:如果根據給定的key獲取到的緩存項為空,那么factory將會創建一個標識符為key的緩存,並且返回該緩存
ICache接口還有其它方法,如前面Clear()
,Get()
,GetOrDefault
,Set
,Remove
和Clear
。當然也有這些方法的異步(async)版本。如下圖,我就懶得寫了。
ITypedCache
ICache
接口用key(字符串類型)來獲取緩存value(object類型)。ITypedCache
為ICahe
提供了一個 類型安全 的包裝;為了使類型安全轉換(ICache
到ITypedCache
),我們可以用擴展方法 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)首先,我們前往https://github.com/dmajkic/redis/downloads下載安裝包,直接下一步下一步就可以了。
然后打開安裝的地址就可以看到如下的文件:
(2)然后啟動Redis服務,我們cmd到安裝目錄下,然后輸入命令redis-server.exe redis.windows.conf
就會看到下面的畫面證明我們啟動服務成功。
abp默認Cache Mananger是使用in-memory來緩存。所以,這可能會成為一個問題,如果有多個並發的Web服務運行在同一個應用中。在這種情況下,你可能想要一個分布式/中央緩存服務器。那么,你可以使用Redis來作為你的緩存服務。
首先,你需要安裝
Abp.RedisCachenuget package 到你的項目中(你可以安裝它到你的Web項目)。這里我遇到一個錯誤。
開始的時候我搞了半天不知道為什么會出現這個莫名其妙的錯誤,后來才發現,原來我引入Abp.RedisCache版本和abp版本不一致。才導致的這個錯誤,比如你abp是3.1.1,那么你的Abp.RedisCache最好也是對應的版本,最好的話把abp和Abp.RedisCache都升級到最新版本,就不會有錯誤了。
然后我們看看Abp.Runtime.Caching.Redis;依賴項以及之間的關系。
然后在ABPCMSWebModule配置一下。
ABPCMSApplicationModule中引入。
Web.config中配置
你也可以添加配置到appSettings來設置Redis數據庫的Id。如:
<add key="Abp.Redis.Cache.DatabaseId" value="2"/>
在同一個服務器上使用不同的數據庫Id是非常有用的這可以創建不同的Key Spaces(隔離緩存)。
UseRedis有一個重載方法,你可以通過這個方法來傳入配置參數,這可以覆蓋掉配置文件中的配置。關於Redis的其他配置可以查看Redis文檔。
在下面UserList打下斷點調試進去。
看到效果如下圖,證明我們AbpRedisCache引入成功。
當然為了更好的進行可視化操作,我建議使用跨平台開源Redis DB管理工具(Redis Desktop Manager)地址:https://redisdesktop.com/download
下載下來直接下一步下一步安裝即可。
然后運行項目,然后我們在看下Redis Desktop Manager工具,效果如下圖:
使用可視化工具很方便
- 新建連接,輸入redis主機host,端口號port,再起個生動形象,簡明達意的別名。
- 該工具支持根據篩選條件查詢key,add new key,reload等。
- 支持常用redis操作,針對目標key執行rename,delete,addrow,reload value操作。
- 命令控制台操作 !大家感興趣可以自己玩一下。
另外關於實體修改后自動更新緩存的實現遠離可以參考
http://www.cnblogs.com/loyldg/p/using-redis-in-abp-2.html
這個文章。
Github項目地址:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
本文鏈接:http://www.cnblogs.com/anyushengcms/p/8013201.html
ABP+AdminLTE+Bootstrap Table權限管理系統一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期