溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C# Memory Cache的坑怎么解決

發(fā)布時(shí)間:2021-12-03 09:15:42 來(lái)源:億速云 閱讀:262 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“C# Memory Cache的坑怎么解決”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“C# Memory Cache的坑怎么解決”吧!

背景

前些天公司服務(wù)器數(shù)據(jù)庫(kù)訪問(wèn)量偏高,運(yùn)維人員收到告警推送,安排我團(tuán)隊(duì)小伙伴排查原因.

我們發(fā)現(xiàn)原來(lái)系統(tǒng)定期會(huì)跑一個(gè)回歸測(cè)試,該測(cè)運(yùn)行的任務(wù)較多,每處理一條任務(wù)都會(huì)到數(shù)據(jù)庫(kù)中取相關(guān)數(shù)據(jù),高速地回歸測(cè)試也帶來(lái)了高頻率的數(shù)據(jù)庫(kù)讀取.

解決方案1

我們認(rèn)為每個(gè)任務(wù)要取的數(shù)據(jù)大相徑庭,因此我們考慮對(duì)這個(gè)過(guò)程進(jìn)行修改,加入MemoryCache把數(shù)據(jù)庫(kù)中讀取到的數(shù)據(jù)進(jìn)行緩存.

整個(gè)修改非常簡(jiǎn)單,相信對(duì)常年混跡在博客園中的各位大佬來(lái)說(shuō)小菜一碟,因此小弟不再敘述添加緩存的步驟細(xì)節(jié).

從緩存的添加,代碼提交,Teamcity 編譯通過(guò),到測(cè)試環(huán)境,QA環(huán)境的安裝無(wú)比流暢,一切顯得如手到擒來(lái).

嗯,優(yōu)秀是一種習(xí)慣, 沒(méi)有一點(diǎn)辦法.

人生如戲,當(dāng)我們還沉浸在"我加的Cache不可能又BUG"的自信中時(shí),QA傳來(lái)噩耗,回歸測(cè)試大量未通過(guò) ....

故障排查

之前習(xí)慣了使用Redis緩存,因此,常識(shí)告訴我們 ---  在數(shù)據(jù)庫(kù)中數(shù)據(jù)沒(méi)有改動(dòng)的前提下,加了緩存后讀取的數(shù)據(jù)的效果和從數(shù)據(jù)庫(kù)中讀取的效果是一模一樣的.

除非  ,,,   除非  這個(gè)常識(shí)是錯(cuò)誤的....

因此我們加了日志,對(duì)寫(xiě)入緩存前后讀取出來(lái)的數(shù)據(jù)進(jìn)行了對(duì)比,結(jié)果出人意料.

C# Memory Cache的坑怎么解決

該死 MemoryCache 毀我老臉,丟我精度,拿命來(lái)!!!!!

從日志中看到,第一行是從數(shù)據(jù)庫(kù)中讀取的結(jié)果,第二行是從cache中讀取的,前兩條數(shù)據(jù)完全一致,到了第三條,第四條,第五條,仔細(xì)觀察發(fā)現(xiàn),在小數(shù)點(diǎn)后面,居然有些小數(shù)點(diǎn)后比較微小的變化,不管變化的大小但數(shù)據(jù)確實(shí)發(fā)生改變了,所以MemoryCache會(huì)影響數(shù)據(jù)精度??這樣會(huì)改變數(shù)據(jù)精度的MemoryCache又有何用?? 

機(jī)智的我,似乎早已看穿了一切,這肯定不是MenoryCache的鍋!!!

不一樣的MemoryCache

我從https://referencesource.microsoft.com 中扒出了MemoryCache的源碼一探究竟.

定位到MemoryCache中的AddOrGetExisting方法,我們看到,其實(shí)我們把數(shù)據(jù)存儲(chǔ)到該緩存的過(guò)程本質(zhì)是把該對(duì)象存到一個(gè)名為_(kāi)entries的         Hashtable 中,同樣,取數(shù)據(jù)也是通過(guò)Key到該Hashtable中取出來(lái),整個(gè)過(guò)程并沒(méi)有對(duì)該對(duì)象進(jìn)行序列化反序列等,也沒(méi)有對(duì)該對(duì)象進(jìn)行clone操作.這就意味著我們之前存入的,和后面取出的(不管我們從MemoryCache中取數(shù)據(jù)取多少次),永遠(yuǎn)只取出同一個(gè)對(duì)象.

這一點(diǎn),和我之前使用的RedisCache是有很大區(qū)別的.我們?cè)赗edis中存入數(shù)據(jù),是把對(duì)象序列化后存到Redis中,取數(shù)據(jù)是把Redis中的字節(jié)數(shù)據(jù)反序列成對(duì)象,意味著前一次存入的,和后一次取出的,已經(jīng)不是同一個(gè)對(duì)象了,因此Redis中的數(shù)據(jù)是安全的.

猜想

我做出了一個(gè)大膽的猜想,之前從MemoryCache中取出來(lái)的數(shù)據(jù)之所以變化了,可能是取出對(duì)象后,復(fù)雜的處理過(guò)程中對(duì)該對(duì)象進(jìn)行了什么修改操作,所以后期,再次從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),讀出來(lái)的已經(jīng)已經(jīng)不是最初存入的數(shù)據(jù),而是前一次修改之后的數(shù)據(jù).帶著這個(gè)猜想,我對(duì)代碼進(jìn)行了修改.

解決方案2

從MenoryCache中取到數(shù)據(jù)后對(duì)結(jié)果進(jìn)行clone(),這樣即使程序?qū)θ〕鰜?lái)的結(jié)果進(jìn)行了修改也不會(huì)影響Cache中的數(shù)據(jù)了.

又是一次提心掉到的提交,編譯,安裝后, 回歸測(cè)試順利通過(guò).

到此,相信大家對(duì)“C# Memory Cache的坑怎么解決”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI