.Net緩存管理框架CacheManager

来源:https://www.cnblogs.com/supersnowyao/archive/2018/01/01/8168014.html
-Advertisement-
Play Games

Cache緩存在電腦領域是一個被普遍使用的概念。硬體中CPU有一級緩存,二級緩存, 瀏覽器中有緩存,軟體開發中也有分散式緩存memcache, redis。緩存無處不在的原因是它能夠極大地提高硬體和軟體的運行速度。在項目開發中,性能慢的地方常常是IO操作頻繁的地方,讀取資料庫是我們常見的消耗性能的 ...


     Cache緩存在電腦領域是一個被普遍使用的概念。硬體中CPU有一級緩存,二級緩存, 瀏覽器中有緩存,軟體開發中也有分散式緩存memcache, redis。緩存無處不在的原因是它能夠極大地提高硬體和軟體的運行速度。在項目開發中,性能慢的地方常常是IO操作頻繁的地方,讀取資料庫是我們常見的消耗性能的地方。這個時候,如果將使用頻繁的數據緩存到能夠高速讀取的介質中,下次訪問時,不用再去請求資料庫,直接從緩存中獲取所需的數據,就能夠大大提高性能。這篇文章主要討論的是在.Net開發中,如何使用CacheManager框架方便的管理項目中的緩存。

 一,CacheManager介紹以及優點

      CacheManager是開源的.Net緩存管理框架。它不是具體的緩存實現,而是在緩存之上,方便開發人員配置和管理各種不同的緩存,為上層應用程式提供統一的緩存介面的中間層。

     下麵是CacheManager的一些優點:

  • 讓開發人員更容易處理和配置緩存,即使是非常複雜的緩存方案。
  • CacheManager能夠管理多種緩存,包含記憶體、appfabric、redis、couchbase、 windows azure cache、memorycache等。
  • 提供了額外的功能,如緩存同步、併發更新、事件、性能計數器等…

 二,CacheManager開始之旅

     CacheManager上手還是非常簡單的。下麵使用記憶體緩存結合CacheManager的一個實例,能夠幫助我們快速的熟悉CacheManager如何使用。

     首先在Visual Studio中創建一個Console Application.

 

     使用Nuget為項目添加CacheManager包引用。CacheManager包含了很多的Package. 其中CacheManager.Core是必須的,其它的針對不同緩存平臺上有不同的對應Package.

     這個Demo中,我們使用記憶體作為緩存,所以只是需要CacheManager.Core和CacheManager.SystemRuntimeCaching

 

     接著在Main函數中配置好我們的緩存:

 1 using System;
 2 using CacheManager.Core;
 3 namespace ConsoleApplication
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             var cache = CacheFactory.Build("getStartedCache", settings =>
10             {
11                 settings.WithSystemRuntimeCacheHandle("handleName");
12             });
13         }
14     }
15 }

 

     上面代碼中使用CacheFactory創建了一個名稱為getStartedCache的緩存實例,這個緩存實例使用的是SystemRunTime Cache, 記憶體緩存。一個緩存實例是可以配置多個Handle的,我們可以使用記憶體來作為存儲介質,也可以使用Redis分散式緩存作為存儲介質,並且可以同時在一個緩存實例中使用,後面我們再介紹多級緩存的配置和使用。

     接下來,我們添加一些測試緩存的代碼

 1 static void Main(string[] args)
 2 {
 4     var cache = CacheFactory.Build("getStartedCache", settings =>
 5     {
 6         settings.WithSystemRuntimeCacheHandle("handleName");
 7     });
 8 
 9     cache.Add("keyA", "valueA");
10     cache.Put("keyB", 23);
11     cache.Update("keyB", v => 42);
12     Console.WriteLine("KeyA is " + cache.Get("keyA"));      // should be valueA
13     Console.WriteLine("KeyB is " + cache.Get("keyB"));      // should be 42
14     cache.Remove("keyA");
15     Console.WriteLine("KeyA removed? " + (cache.Get("keyA") == null).ToString());
16     Console.WriteLine("We are done...");
17     Console.ReadKey();
18 }

 

三,CacheManager多級緩存配置

     實際開發中,我們常常會需要使用多級緩存。

     一種常見的情況是,你有一個分散式式緩存伺服器,例如redis,獨立的緩存伺服器能夠讓我們的多個系統應用程式都能夠共用這些緩存的數據,因為這些緩存項的創建是昂貴的。

     和訪問資料庫相比,分散式緩存速度較快,但是和記憶體相比,還是不夠快。因為分散式緩存使用還需要序列化和網路傳輸的時間消耗。

     這個時候里,做個分級緩存是個好的解決方案,將記憶體緩存結合分散式緩存使用,使用頻率高的數據直接從記憶體中讀取,這將大大提高應用程式的整體性能。

     使用記憶體緩存的讀取速度能夠達到分散式緩存的100倍,甚至更高。

     使用CacheManager, 配置多級緩存是一件非常容易的事情

 1 var cache = CacheFactory.Build<int>("myCache", settings =>
 2 {
 3     settings
 4         .WithSystemRuntimeCacheHandle("inProcessCache")//記憶體緩存Handle
 5         .And
 6         .WithRedisConfiguration("redis", config =>//Redis緩存配置
 7         {
 8             config.WithAllowAdmin()
 9                 .WithDatabase(0)
10                 .WithEndpoint("localhost", 6379);
11         })
12         .WithMaxRetries(1000)//嘗試次數
13         .WithRetryTimeout(100)//嘗試超時時間
14         .WithRedisBackPlate("redis")//redis使用Back Plate
15         .WithRedisCacheHandle("redis", true);//redis緩存handle
16 });

 

      上面代碼中,記憶體緩存和Redis緩存配置部分很容易看明白。但是BackPlate是什麼作用? 接下來,我們看看CacheManager中的BackPlate擋板機制。

 四, BackPlate解決分散式緩存中的同步問題

     對於大型的軟體系統,常常都是分為很多獨立的子項目,各個子項目為了節約成本或者是方便數據共用,常常會共用同一個分佈緩存伺服器。這樣在使用多級緩存的時候,就有可能出現數據不一致的情況。

     假設在系統A中的更新了緩存中的一個數據項,這個時候CacheManager會在A設置的所有的緩存handle中更新數據,這裡也包括了分散式緩存上的數據。但是在系統B中的記憶體緩存中,還是會存在著舊的未更新的數據。當系統B從緩存中取這條記錄的時候,就會出現記憶體緩存和分散式緩存中的數據不一致的情況。

     為了防止這一點,緩存管理器有一個功能叫做cachebackplate將嘗試同步多個系統中的緩存。

     上面設置的多級緩存中,我們就將redis作為BackPlate的源. 也就是說所有的數據都需要以redis中緩存的數據為藍本。

     在設置redis作為BackPlate之後,同樣發生上面的數據不一致的情況的時候,只要redis中的數據被修改了,就會觸發CacheManager更新所有系統中的記憶體緩存中的數據,和redis中的數據保持一致。

     同步的工作是如何完成的?

     每次一條緩存記錄被刪除或更新的時候,Cache Manager會發送一個消息,讓BackPlate存儲這次的數據變化信息。所有其它的系統將非同步接收這些消息,並將相應地作出更新和刪除操作,保證數據的一致性。

五,ExpirationMode和CacheUpdateMode

     涉及到緩存,就必然有緩存過期的問題。CacheManager中提供了一些簡單的緩存過期方式設置。

1 public enum ExpirationMode
2 {
3     None = 0,
4     Sliding = 1,
5     Absolute = 2,
6 }

 

     同時CacheManager還為多級緩存之間設置不同的數據更新策略

1 public enum CacheUpdateMode
2 {
3     None = 0,
4     Full = 1,
5     Up = 2,
6 }

 

     使用Sliding和Up, 我們我可以為多級緩存設置不同的緩存過期時間,這樣使用頻率高的數據就能夠保存在訪問速度更快的記憶體中,訪問頻率次高的放到分散式緩存中。當CacheManager在記憶體中找不到緩存數據的時候,就會嘗試在分散式緩存中找。找到後,根據Up設置,會再將該緩存數據保存到記憶體緩存中。

     具體的配置方式如下:

 1 var cache = CacheFactory.Build<int>("myCache", settings =>
 2 {
 3     settings.WithUpdateMode(CacheUpdateMode.Up)
 4         .WithSystemRuntimeCacheHandle("inProcessCache")//記憶體緩存Handle
 5         .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60)))
 6         .And
 7         .WithRedisConfiguration("redis", config =>//Redis緩存配置
 8         {
 9             config.WithAllowAdmin()
10                 .WithDatabase(0)
11                 .WithEndpoint("localhost", 6379);
12         }).
13         .WithExpiration(ExpirationMode.Sliding, TimeSpan. FromHours  (24)))
14         .WithMaxRetries(1000)//嘗試次數
15         .WithRetryTimeout(100)//嘗試超時時間
16         .WithRedisBackPlate("redis")//redis使用Back Plate
17         .WithRedisCacheHandle("redis", true);//redis緩存handle
18 
19 });

 

六,緩存使用分析

     在緩存使用中,對於緩存hit和miss數據態比較關係,這些數據能夠幫助我們分析和調整緩存的設置,幫助緩存使用地更加合理。

1 var cache = CacheFactory.Build("cacheName", settings => settings
2     .WithSystemRuntimeCacheHandle("handleName")
3         .EnableStatistics()
4         .EnablePerformanceCounters());

 

     在配置好緩存的Statistic功能後,我們就能夠跟蹤到緩存的使用情況了, 下麵就是分別列印各個緩存handle中的分析數據。

 1 foreach (var handle in cache.CacheHandles)
 2 {
 3     var stats = handle.Stats;
 4     Console.WriteLine(string.Format(
 5             "Items: {0}, Hits: {1}, Miss: {2}, Remove: {3}, ClearRegion: {4}, Clear: {5}, Adds: {6}, Puts: {7}, Gets: {8}",
 6                 stats.GetStatistic(CacheStatsCounterType.Items),
 7                 stats.GetStatistic(CacheStatsCounterType.Hits),
 8                 stats.GetStatistic(CacheStatsCounterType.Misses),
 9                 stats.GetStatistic(CacheStatsCounterType.RemoveCalls),
10                 stats.GetStatistic(CacheStatsCounterType.ClearRegionCalls),
11                 stats.GetStatistic(CacheStatsCounterType.ClearCalls),
12                 stats.GetStatistic(CacheStatsCounterType.AddCalls),
13                 stats.GetStatistic(CacheStatsCounterType.PutCalls),
14                 stats.GetStatistic(CacheStatsCounterType.GetCalls)
15             ));
16 }

 

七,結尾

     緩存是個好東西,用好了能夠極大的提高性能。緩存的使用本身是個很大的話題,這邊文章只是從緩存管理這個角度介紹了CachManager的使用。

     下麵是CacheManager相關的資料和鏈接:

     官方主頁

     http://cachemanager.net/

     源代碼

     https://github.com/MichaCo/CacheManager

     官方MVC項目的Sample

     https://github.com/MichaCo/CacheManager/tree/master/samples/CacheManager.Samples.Mvc

     最近在思考不同情況下緩存使用的區別問題。對於互聯網項目來說,數據的一致性要求常常不太高,緩存管理中,關註點可能在緩存的命中率上。對於應用系統,訪問請求不大,但是對於數據的一致性要求較高,緩存中的數據更新策略可能更加重要。

怎樣才是好的適合應用系統的緩存設計呢? 如果大家有興趣,歡迎探討指教。

文章轉載自:http://www.cnblogs.com/JustRun1983/p/CacheManager.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在工作中碰到了一個問題,原本在IE8,IE9下正常的input表單,在IE10下會出現清除按鈕,即表單右側會出現一個可以清除該表單內容的小叉。由於之前一直沒有相容過IE10,所以我專門搜了下原因。發現,該功能是微軟在IE10上新添加的功能,用於快速清空表單值。 而問題是,工作中使用到的表單控制項以 ...
  • 之前寫完vue項目後,佈置到伺服器,用nginx反向代理後,一開始進去,進各種路由都是沒問題的,但是一旦f5刷新後就會出現一個nginx404的錯誤。 經過翻閱vue文檔後,發現這是vueHistory 模式下的一個問題,需要後臺配置支持。 History 模式是沒有hash鍵,比如/a/b,f5刷 ...
  • 前言 這裡分享一個博主寫的省市區三級菜單聯動插件 — jQuery Citys,此插件中所有省市區數據均為國家行政區劃代碼,保證數據真實可靠,插件可以根據預設地區代碼或地區名稱進行值的初始化操作。 線上演示地址:https://yangyunhe369.github.io/jQuery Citys ...
  • 無限滾動載入最佳實踐 無限滾動(Infinite scrolling),有時候被稱為無盡滾動(endless scrolling),這種技術允許用戶在大量內容上滾動,眼中看不到結束的地方。這種技術很簡單,就是頁面往下滾動的時候保持刷新。 這項技術使用戶在沒有 打斷 和 額外交互 的情況下滾動列表 — ...
  • Promise API 簡介 譯者註: 到處是回調函數,代碼非常臃腫難看, Promise 主要用來解決這種編程方式, 將某些代碼封裝於內部。 Promise 直譯為“承諾”,但一般直接稱為 Promise; 代碼的可讀性非常重要,因為開發人員支出一般比電腦硬體的支出要大很多倍。 雖然同步代碼更容 ...
  • 在HTML5的規範中,我們可以通過為元素增加`draggable="true"`來設置此元素是否可以進行拖拽操作,其中圖片、鏈接預設是開啟的。 1. 拖拽元素:設置了`draggable="true"`的元素 當拖動某元素時,將依次觸發下列事件: 1. dragstart(按下滑鼠並開始移動滑鼠時, ...
  • 13.Label的作用是什麼?是怎麼用的? label標簽來定義表單控制間的關係,當用戶選擇該標簽時,瀏覽器會自動將焦點轉到和標簽相關的表單事件上。 <label for="Name">Number:</label> <input type="text" name="Name" id="Name"/ ...
  • 開篇 天天逛博客園,就是狠不下心來寫篇博客,忙是一方面,但是說忙能有多忙呢,都有時間逛博客園,寫篇博客的時間都沒有?(這還真不好說) 每次想到寫一篇新的設計模式,我總會問自己: 1,自己理解了嗎? 2,我能以一種簡單且有邏輯的方式把它說出來嗎? 不說做到有的放矢,但是一本正經的胡說八道還是要有吧,起 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...