程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> .NET緩存框架CacheManager在混合式開發框架中的應用(1)-CacheManager的介紹和使用,cachemanager

.NET緩存框架CacheManager在混合式開發框架中的應用(1)-CacheManager的介紹和使用,cachemanager

編輯:C#入門知識

.NET緩存框架CacheManager在混合式開發框架中的應用(1)-CacheManager的介紹和使用,cachemanager


在我們開發的很多分布式項目裡面(如基於WCF服務、Web API服務方式),由於數據提供涉及到數據庫的相關操作,如果客戶端的並發數量超過一定的數量,那麼數據庫的請求處理則以爆發式增長,如果數據庫服務器無法快速處理這些並發請求,那麼將會增加客戶端的請求時間,嚴重者可能導致數據庫服務或者應用服務直接癱瘓。緩存方案就是為這個而誕生,隨著緩存的引入,可以把數據庫的IO耗時操作,轉換為內存數據的快速響應操作,或者把整個頁面緩存到緩存系統裡面。緩存框架在各個平台裡面都有很多的實現,基本上多數是采用分布式緩存Redis、Memcached來實現。本系列文章介紹在.NET平台中,使用開源緩存框架CacheManager來實現數據的緩存的整個過程,本篇主要介紹CacheManager的使用和相關的測試。

1、CacheManager的介紹

CacheManager是一個以C#語言開發的開源.Net緩存框架抽象層。它不是具體的緩存實現,但它支持多種緩存提供者(如Redis、Memcached等)並提供很多高級特性。
CacheManager 主要的目的使開發者更容易處理各種復雜的緩存場景,使用CacheManager可以實現多層的緩存,讓進程內緩存在分布式緩存之前,且僅需幾行代碼來處理。
CacheManager 不僅僅是一個接口去統一不同緩存提供者的編程模型,它使我們在一個項目裡面改變緩存策略變得非常容易,同時也提供更多的特性:如緩存同步、並發更新、序列號、事件處理、性能計算等等,開發人員可以在需要的時候選擇這些特性。

CacheManager的GitHub源碼地址為:https://github.com/MichaCo/CacheManager,如果需要具體的Demo及說明,可以訪問其官網:http://cachemanager.net/。

使用Nuget為項目添加CacheManager包引用。CacheManager包含了很多的Package. 其中CacheManager.Core是必須的,其它的針對不同緩存平台上有不同的對應Package,整個Nuget包包含下面幾個部分的內容。

CacheManager緩存框架支持Winform和Web等應用開發,以及支持多種流行的緩存實現,如MemoryCache、Redis、Memcached、Couchbase、System.Web.Caching等。

縱觀整個緩存框架,它的特定很明顯,在支持多種緩存實現外,本身主要是以內存緩存(進程內)為主,其他分布式緩存為輔的多層緩存架構方式,以達到快速命中和處理的機制,它們內部有相關的消息處理,使得即使是分布式緩存,也能夠及時實現並發同步的緩存處理。

在網上充斥著基於某種單獨緩存的實現和應用的趨勢下,這種更抽象一層,以及提供更高級特性的緩存框架,在提供了統一編程模型的基礎上,也實現了非常強大的兼容性,使得我一接觸到這個框架,就對它愛不釋手。

在GitHub上,緩存框架的前幾名,除了這個緩存框架外,也還有一些,不過從文檔的豐富程度等各方面來看,這個緩存框架還是非常值得擁有的。

CacheManager緩存框架在配置方面,支持代碼方式的配置、XML配置,以及JSON格式的配置處理,非常方便。

CacheManager緩存框架默認對緩存數據的序列化是采用二進制方式,同時也支持多種自定義序列化的方式,如基於JOSN.NET的JSON序列化或者自定義序列化方式。

CacheManager緩存框架可以對緩存記錄的增加、刪除、更新等相關事件進行記錄。

CacheManager緩存框架的緩存數據是強類型的,可以支持各種常規類型的處理,如Int、String、List類型等各種基礎類型,以及可序列號的各種對象及列表對象。

CacheManager緩存框架支持多層的緩存實現,內部良好的機制可以高效、及時的同步好各層緩存的數據。

CacheManager緩存框架支持對各種操作的日志記錄。

CacheManager緩存框架在分布式緩存實現中支持對更新的鎖定和事務處理,讓緩存保持更好的同步處理,內部機制實現版本沖突處理。

CacheManager緩存框架支持兩種緩存過期的處理,如絕對時間的過期處理,以及固定時段的過期處理,是我們處理緩存過期更加方便。

....

很多特性基本上覆蓋了緩存的常規特性,而且提供的接口基本上也是我們所經常用的Add、Put、Update、Remove等接口,使用起來也非常方便。

 

2、CacheManager緩存框架的應用

通過上面對CacheManager緩存框架的簡單了解,我們大概了解了它應用的一些功能,但是實際上我們如何使用它,我們需要做一些學習和了解,首先我們需要在整個應用框架裡面,知道緩存框架所扮演的角色。

一般來說,對於單機版本的應用場景,基本上是無需引入這種緩存框架的,因為客戶端的並發量很少,而且數據請求也是寥寥可數的,性能方便不會有任何問題。

如果對於分布式的應用系統,如我在很多隨筆中介紹到我的《混合式開發框架》、《Web開發框架》,由於數據請求是並發量隨著用戶增長而增長的,特別對於一些互聯網的應用系統,極端情況下某個時間點一下可能就會達到了整個應用並發的峰值。那麼這種分布式的系統架構,引入數據緩存來降低IO的並發數,把耗時請求轉換為內存的高速請求,可以極大程度的降低系統宕機的風險。

我們以基於常規的Web API層來構建應用框架為例,整個數據緩存層,應該是在Web API層之下、業務實現層之上的一個層,如下所示。

在這個數據緩存層裡面,我們引入了CacheManager緩存框架,實現分布式的緩存處理,使得我們的緩存數據能夠在Redis服務器上實現數據的處理,同時可以在系統重啟的時候,不至於丟失數據,能夠快速恢復緩存數據。

為了實現對這個CacheManager緩存框架的使用,我們需要先進行一個使用測試,以便了解它的各個方便情況,然後才能廣泛應用在我們的數據中間層上。

我們建立一個項目,並在引用的地方打開管理NuGet程序包,然後搜索到CacheManager的相關模塊應用,並加入到項目引用裡面,此為第一步工作。

我們創建一個客戶對象類,用來模擬數據的存儲和顯示的,如下代碼所示。

/// <summary>
/// 模擬數據存儲的客戶對象類
/// </summary>
public class Customer
{
    private static Customer m_Customer = null;
    private static ICacheManager<object> manager = null;

    //初始化列表值
    private static List<string> list = new List<string>() { "123", "456", "789" };

    /// <summary>
    /// 客戶對象的單件實例
    /// </summary>
    public static Customer Instance
    {
        get
        {
            if(m_Customer == null)
            {
                m_Customer = new Customer();
            }
            if (manager == null)
            {
                manager = CacheFactory.Build("getStartedCache", settings =>
                {
                    settings.WithSystemRuntimeCacheHandle("handleName");
                }); 
            }

            return m_Customer;
        }
    }

這個類先做了一個單例的實現,並初始化緩存Customer類對象,以及緩存管理類ICacheManager<object> manager,這個是我們後面用來操作緩存數據的主要引用對象。

我們編寫幾個函數,用來實現對數據的獲取,數據增加、數據刪除的相關操作,並在數據增加、刪除的時候,觸發緩存的更新,這樣我們下次獲取數據的時候,就是最新的數據了。

/// <summary>
/// 獲取所有客戶信息
/// </summary>
/// <returns></returns>
public List<string> GetAll()
{
    var value = manager.Get("GetAll") as List<string>;
    if(value == null)
    {
        value = list;//初始化並加入緩存
        manager.Add("GetAll", value);

        Debug.WriteLine("初始化並加入列表");
    }
    else
    {
        Debug.WriteLine("訪問緩存獲取:{0}", DateTime.Now);
    }
    return value;
}

/// <summary>
/// 插入新的記錄
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Insert(string customer)
{
    //先獲取全部記錄,然後加入記錄
    if (!list.Contains(customer))
    {
        list.Add(customer);
    }

    //重新設置緩存
    manager.Update("GetAll", v => list);
    return true;
}

/// <summary>
/// 刪除指定記錄
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Delete(string customer)
{
    if(list.Contains(customer))
    {
        list.Remove(customer);
    }
    manager.Update("GetAll", v=>list);
    return true;
}

我們編寫一個Winform程序來對這個緩存測試,以方便了解其中的機制。

我們在測試讀取的時候,也就是對GetAll進行處理,插入以及刪除主要就是為了測試緩存更新的處理。代碼如下所示。

private void btnTestSimple_Click(object sender, EventArgs e)
{
    var list = Customer.Instance.GetAll();
    Debug.WriteLine("客戶端獲取記錄數:{0}", list != null ? list.Count : 0);
}

private void btnInsert_Click(object sender, EventArgs e)
{
    var name = "abc";
    Customer.Instance.Insert(name);
    Debug.WriteLine(string.Format("插入記錄:{0}", name));
}

private void btnDelete_Click(object sender, EventArgs e)
{
    var name = "abc";
    Customer.Instance.Delete(name);
    Debug.WriteLine(string.Format("刪除記錄:{0}", name));
}

我們跟蹤記錄,可以看到下面的日志信息。

我們可以看到,其中第一次是緩存沒有的情況下進行初始化,初始化的記錄數量為3個,然後插入記錄後,再次獲取數據的時候,緩存更新後的數量就變為4個了。

我們前面介紹了插入記錄的後台代碼,它同時進行了緩存數據的更新了。

/// <summary>
/// 插入新的記錄
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
public bool Insert(string customer)
{
    //先獲取全部記錄,然後加入記錄
    if (!list.Contains(customer))
    {
        list.Add(customer);
    }

    //重新設置緩存
    manager.Update("GetAll", v => list);
    return true;
}

我們前面介紹的緩存初始化配置的時候,默認是使用內存緩存的,並沒有使用分布式緩存的配置,它的初始化代碼如下:

manager = CacheFactory.Build("getStartedCache", settings =>
{
    settings.WithSystemRuntimeCacheHandle("handleName");
}); 

我們在正常情況下,還是需要使用這個強大的分布式緩存的,例如我們可以使用Redis的緩存處理,關於Redis的安裝和使用,請參考我的隨筆《基於C#的MongoDB數據庫開發應用(4)--Redis的安裝及使用》。

引入分布式的Redis緩存實現,我們的配置代碼只需要做一定的改變即可,如下所示。

manager = CacheFactory.Build("getStartedCache", settings =>
{
    settings.WithSystemRuntimeCacheHandle("handleName")

    .And
    .WithRedisConfiguration("redis", config =>
    {
        config.WithAllowAdmin()
            .WithDatabase(0)
            .WithEndpoint("localhost", 6379);
    })
    .WithMaxRetries(100)
    .WithRetryTimeout(50)
    .WithRedisBackplane("redis")
    .WithRedisCacheHandle("redis", true)
    ;
}); 

其他的使用沒有任何變化,我們同時增加一些測試數據方便我們查閱對應的緩存數據。

/// <summary>
/// 測試加入幾個不同的數據
/// </summary>
/// <returns></returns>
public void TestCache()
{
    manager.Put("string", "abcdefg");
    manager.Put("int", 2016);
    manager.Put("decimal", 2016.9M);
    manager.Put("date", DateTime.Now);
    manager.Put("object", new UserInfo { ID = "123", Name = "Test", Age = 35 });
}
private void btnTestSimple_Click(object sender, EventArgs e)
{
    var list = Customer.Instance.GetAll();
    Debug.WriteLine("客戶端獲取記錄數:{0}", list != null ? list.Count : 0);

    //測試加入一些值
    Customer.Instance.TestCache();
}

我們其中測試,一切和原來沒有什麼差異,程序的記錄信息正常。

但是我們配置使用了Redis的緩存處理,因此可以使用“Redis Desktop Manager”軟件來查看對應的緩存數據的,打開軟件我們可以看到對應的緩存記錄如下所示。

從上圖我們可以查看到,我們添加的所有緩存鍵值都可以通過這個Redis的客戶來進行查看,因為我們緩存裡面有基於Redis緩存的實現,同理如果我們配置其他的緩存實現,如MemCache等,那麼也可以在對應的管理界面上查看到。

我們完成這些處理後,可以發現緩存數據是可以實現多層緩存的,最為高效的就是內存緩存(也是它的主緩存),它會自動協同好各個分布式緩存的數據版本沖突問題。

引入如Redis的分布式緩存有一個好處,就是我們的數據可以在程序重新啟動的時候,如果沒有在內存緩存裡面找到(沒有擊中目標),那麼會尋找分布式緩存並進行加載,從而即使程序重啟,我們之前的緩存數據依舊保存完好。

 

以上就是我基於對緩存框架的整體了解和其角色扮演做的相關介紹,以及介紹CacheManager的使用和一些場景的說明,通過上面簡單案例的研究,我們可以逐步引入到更具實際價值的Web API 框架層面上進行使用,以期把緩存框架發揮其真正強大的價值,同時也為我們各種不同的緩存需要進行更高層次的探索,希望大家繼續支持。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved