如何使用 Memory Cache 與 Redis Cache

使用 Cache 的目地不外乎是為了避免經常性取資料,另一方面也是為了減輕 DB 的負擔而使用,最常見的不外乎是 run time cache 與 redis cache,而這兩者有什麼不同?

Memory Cache

Memory cache 主要是單一 server 裡存放在記憶體的資料

寫入的方式非常簡單

        public string SetMemeryCache(string name, string value)
        {
            string key = name;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            HttpRuntime.Cache[key] = value;
            sw.Stop();
            return $"write to in memery cache, it takes {sw.ElapsedMilliseconds} mili-secs";
        }

若要指定 cache 的過期時間則要使用另一種寫法

                 HttpRuntime.Cache.Insert(
                 key
                 , value
                 , null
                 , DateTime.Now.AddMinutes( 10 )
                 , Cache.NoSlidingExpiration
                 );

取得的方式也非常簡單

        public string GetMemeryCache(string name)
        {
            string key = name;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var value = HttpRuntime.Cache[key];
            sw.Stop();
            return $"read from in memery cache, it takes {sw.ElapsedMilliseconds} mili-secs, value is {value.ToString()}";
        }

優點:
以實測來講 Set, Get 幾乎是花不到什麼時間,幾乎都是在 10ms 以下的時間

缺點:
Cache 重新啟動程式後即會消失

Redis Cache 

上述所提的 memory cache 是個不錯的做法,然後 redis cache 的出現,則是要解決其他的問題

若是透過 load balance 指到的機器共有三台,但快取的方式都使用了 memory cache 的方式

在資源上等同於存了三份一樣的東西,如果今天 cache 的 key-value 集合數高達數萬筆以上

等同於是浪費了許多資源在做一樣的事情

所以 redis cache 在 load balance 的環境上是相當常見的使用方式

官方文件也有寫出怎麼快速建立 azure redis cache 

初始化  redis  cache, 這裡習 GetDatabase 初始化若不指定則為第 0 個 redis db

        IDatabase cache = lazyConnection.Value.GetDatabase();


        private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
        {
            string cacheConnection = ConfigurationManager.AppSettings["RedisCacheConnection"].ToString();
            return ConnectionMultiplexer.Connect(cacheConnection);
        });

        public static ConnectionMultiplexer Connection
        {
            get
            {
                return lazyConnection.Value;
            }
        }

 

寫入

        public string setCache(string name, string value)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();           
            cache.StringSet(name, value, new TimeSpan(0, 1, 0));
            sw.Stop();
            return $"write to cache, it takes {sw.ElapsedMilliseconds} mili-secs";
        }

取出 

        public string getCache(string name)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var value = cache.StringGet(name);
            sw.Stop();
            return $"get from cache, value is {value}, it takes {sw.ElapsedMilliseconds} mili-secs";
        }

測試下來,讀取與寫入小量資料大約都落在 50-60ms 左右

雖然不像 memory cache 那麼快,但為了省空間與解決 load balance 的問題來說也算是效能不錯的工具

Redis 管理工具

由於資料是寫到 redis 上,有時候想看即時資料要寫測試程式也略顯麻煩

可以使用 Redis Desktop Manager 這套工具,最新版本是要錢的,但舊一點的版本還不需要收費

上面所講的 lazyConnection.Value.GetDatabase(); 沒有指定的話即是寫到 db0 去

可視自己使用的情況去存到不同的 db 去

 

以管理介面來說,甚至可以 rename key 與查看 TTL (以這個例子來說只剩 18 秒有效) ,可說是相當方便的工具

參考文件:

https://docs.microsoft.com/zh-tw/azure/azure-cache-for-redis/cache-dotnet-how-to-use-azure-redis-cache

https://github.com/uglide/RedisDesktopManager/releases