C Memory Cache 踩坑記錄

2022-01-12 19:38:49 字數 1672 閱讀 8227

前些天公司伺服器資料庫訪問量偏高,運維人員收到告警推送,安排我團隊小夥伴排查原因.

我們發現原來系統定期會跑乙個回歸測試,該測執行的任務較多,每處理一條任務都會到資料庫中取相關資料,高速地回歸測試也帶來了高頻率的資料庫讀取.

我們認為每個任務要取的資料大相徑庭,因此我們考慮對這個過程進行修改,加入memorycache把資料庫中讀取到的資料進行快取.

整個修改非常簡單,相信對常年混跡在中的各位大佬來說小菜一碟,因此小弟不再敘述新增快取的步驟細節.

從快取的新增,**提交,teamcity 編譯通過,到測試環境,qa環境的安裝無比流暢,一切顯得如手到擒來.

嗯,優秀是一種習慣, 沒有一點辦法.

人生如戲,當我們還沉浸在"我加的cache不可能又bug"的自信中時,qa傳來噩耗,回歸測試大量未通過 ....

之前習慣了使用redis快取,因此,常識告訴我們 ---  在資料庫中資料沒有改動的前提下,加了快取後讀取的資料的效果和從資料庫中讀取的效果是一模一樣的.

除非  ,,,   除非  這個常識是錯誤的....

因此我們加了日誌,對寫入快取前後讀取出來的資料進行了對比,結果出人意料.

該死 memorycache 毀我老臉,丟我精度,拿命來!!!!!

從日誌中看到,第一行是從資料庫中讀取的結果,第二行是從cache中讀取的,前兩條資料完全一致,到了第三條,第四條,第五條,仔細觀察發現,在小數點後面,居然有些小數點後比較微小的變化,不管變化的大小但資料確實發生改變了,所以memorycache會影響資料精度??這樣會改變資料精度的memorycache又有何用?? 

機智的我,似乎早已看穿了一切,這肯定不是menorycache的鍋!!!

我從 中扒出了memorycache的原始碼一**竟.

定位到memorycache中的addorgetexisting方法,我們看到,其實我們把資料儲存到該快取的過程本質是把該物件存到乙個名為_entries的         hashtable 中,同樣,取資料也是通過key到該hashtable中取出來,整個過程並沒有對該物件進行序列化反序列等,也沒有對該物件進行clone操作.這就意味著我們之前存入的,和後面取出的(不管我們從memorycache中取資料取多少次),永遠只取出同乙個物件.

這一點,和我之前使用的rediscache是有很大區別的.我們在redis中存入資料,是把物件序列化後存到redis中,取資料是把redis中的位元組資料反序列成物件,意味著前一次存入的,和後一次取出的,已經不是同乙個物件了,因此redis中的資料是安全的.

我做出了乙個大膽的猜想,之前從memorycache中取出來的資料之所以變化了,可能是取出物件後,複雜的處理過程中對該物件進行了什麼修改操作,所以後期,再次從資料庫中讀取資料,讀出來的已經已經不是最初存入的資料,而是前一次修改之後的資料.帶著這個猜想,我對**進行了修改.

從menorycache中取到資料後對結果進行clone(),這樣即使程式對取出來的結果進行了修改也不會影響cache中的資料了.

又是一次提心掉到的提交,編譯,安裝後, 回歸測試順利通過.

感覺人生到達了高潮   -_-

把踩得坑分享出來,希望後面的小夥伴引以為鑑,

mybatis LocalCache踩坑記錄

上週週三下午,準備去吃飯的時候,值班突然找過來說使用者操作時爆出訂單不存在的問題,因為之前做了分表連續很長一段時間都沒問題,而且當時找過來的都是一些因為產品或者qa操作不當找不到記錄的情況,就沒有在意這些,當時以為幾分鐘就能搞定,但是沒想到居然是線上日誌爆出的問題,經過驗證訂單確實不存在!心想完了,...

AdMob接入踩坑記

首先列出參考文件 admob官方參考鏈結 我是cocos2d x v3.9的工程,在按照官方文件接入之後,出現一堆編譯錯誤例如 plain view plain copy undefined symbols for architecture arm64 objc class glkview refe...

python codecs 模組踩坑記

之前在使用 codecs 模組進行檔案讀寫的時候,常用習慣 如下 import codecs 讀取data codecs.open file name r utf 8 read 寫入fw codecs.open file name w utf 8 fw.write data 之前這麼寫好像也沒什麼問...