.net core系列之《在.net core中使用MemoryCache實現本地緩存》


說到內存緩存MemoryCache不由的讓我想起.Net Framework中的MemoryCache,它位於 System.Runtime.Caching 程序集中。

接下來我們來看看.net core中的MemoryCache又有什么與眾不同的地方吧。

一、基本實現

  1、打開NuGet包管理器搜索並安裝 Microsoft.Extensions.Caching.Memory 包,或者從程序包管理控制台執行 Install-Package Microsoft.Extensions.Caching.Memory 命令

  2、接下來看實現代碼

        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
            memoryCache.Set("name","tom");
            var value = memoryCache.Get("name");
            Console.WriteLine(value);

            Console.ReadKey();
        }

  結果如下:

  

二、緩存容量控制:SizeLimit

  1、當你用SizeLimit屬性設置了這個緩存大小之后,你就必須為你緩存中的每一項設置大小,否則則報錯。當然,當你的大小達到你設置的SizeLimit時,你再設置緩存,它會自動清理一些緩存再緩存你設置的值

  2、代碼如下:

        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
            {
                SizeLimit = 100
            });
            for (int i = 0; i < 1000; i++)
            {
                memoryCache.Set<int>(i.ToString(), i, new MemoryCacheEntryOptions() {
                    Size = 1
                });
            }
            Console.WriteLine(memoryCache.Count);

            Console.ReadKey();
        }

  結果如下:

  

  實際結果不是1000,而是100

  我們來看看它設置值的過程是什么樣的:

  

  由於設置的大小為100,達到100時再設置緩存項就會自動清理掉一部分

三、緩期的過期問題

1、被動過期

  代碼如下:

        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
            memoryCache.Set("name", "jack", new MemoryCacheEntryOptions()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(5)//設置為5秒后過期
            });
            while (true)
            {
                System.Threading.Thread.Sleep(1000);
                string value;
                if (!memoryCache.TryGetValue("name", out value))
                {
                    value = "已過期";
                }
                Console.WriteLine(value);
            }
            //Console.ReadKey();
        }

  結果如下:

  

2、主動過期

        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            var cacheOptins = new MemoryCacheEntryOptions()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期
            };
            cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));

            memoryCache.Set("name", "jack", cacheOptins);

            tokenSource.CancelAfter(2000);//主動設置為2秒過期
            while (true)
            {
                Thread.Sleep(1000);
                string value;
                if (!memoryCache.TryGetValue("name", out value))
                {
                    value = "已過期";
                }
                Console.WriteLine(value);
            }
            //Console.ReadKey();
        }

  結果如下:

  

3、過期后回調:  

  static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            var cacheOptins = new MemoryCacheEntryOptions()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期
            };
            cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));

            cacheOptins.RegisterPostEvictionCallback((key, value, reason, state) => {              Console.WriteLine(reason);             });

            memoryCache.Set("name", "jack", cacheOptins);

            tokenSource.CancelAfter(2000);//主動設置為2秒過期
            while (true)
            {
                Thread.Sleep(1000);
                string value;
                if (!memoryCache.TryGetValue("name", out value))
                {
                    value = "已過期";
                }
                Console.WriteLine(value);
            }
            //Console.ReadKey();
        }

  結果如下:

  

四、其它的一些設置

1、原子性操作

 memoryCache.GetOrCreate("name", entry => "lucy");

2、優先級設置,這個設置是為了配合壓縮緩存的

以下是系統定義的優先級的枚舉

    public enum CacheItemPriority
    {
        Low = 0,
        Normal = 1,
        High = 2,
        NeverRemove = 3
    }

接下來設定優先級

 var cacheOptins = new MemoryCacheEntryOptions()
            {
                Priority= CacheItemPriority.Low,
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期
            };

3、緩存壓縮

        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
            {
                SizeLimit = 100
            });
            for (int i = 0; i < 100; i++)
            {
                CacheItemPriority priority = CacheItemPriority.Low;
                if (25 < i && i < 50)
                    priority = CacheItemPriority.Normal;
                else if (50 < i && i < 75)
                    priority = CacheItemPriority.High;
                else
                    priority = CacheItemPriority.NeverRemove;
                memoryCache.Set(i.ToString(), i.ToString(), new MemoryCacheEntryOptions()
                {
                    Size = 1,
                    Priority = priority,
                    AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期
                });
            }
            memoryCache.Compact(0.2);//壓縮20%
            Console.WriteLine(memoryCache.Count);
            for (int i = 0; i < 100; i++)
            {
                Console.WriteLine(memoryCache.Get(i.ToString()));
            }
            Console.ReadKey();
        }

結果如下:

壓縮后的緩存項數:

被壓縮的緩存項:

根據結果可知道,優先級為 CacheItemPriority.Normal 的數據被壓縮掉了,由此可見,優先級為 CacheItemPriority.Low 的並沒有參加壓縮。

壓縮的優先級順序是 CacheItemPriority.Normal>CacheItemPriority.High>CacheItemPriority.NeverRemove 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM