那些把程序猿坑慘的緩存設(shè)置

作者:杜偉

在碼農(nóng)的世界里箕肃,一直以來(lái)都有一個(gè)信仰:只要應(yīng)用使用了緩存茉帅,性能就會(huì)翻倍;用上緩存的應(yīng)用就像是打通任督二脈的武林高手涨冀,內(nèi)力生生不息。但是今天我想跟各位猿類朋友聊一聊自己在使用緩存時(shí)遇到的那些坑(這里主要講對(duì)象緩存應(yīng)用部分麦萤,想了解全面的推薦閱讀《架構(gòu)真經(jīng)》)鹿鳖。

案例一

前幾天突然發(fā)現(xiàn) Redis 監(jiān)控顯示某 Redis 實(shí)例內(nèi)存使用量突破了 14G 大關(guān)扁眯,當(dāng)時(shí)我就震驚了,這是要翻車的節(jié)奏啊翅帜。通過(guò) info 指令查看姻檀,發(fā)現(xiàn) key 的量并不是太高,所以懷疑有個(gè)別業(yè)務(wù) value 的 size 比較大涝滴,為了保證生產(chǎn)不受影響绣版,從生產(chǎn)上導(dǎo)出 rdb 文件進(jìn)行分析。通過(guò)

rdb -c memory redis_dump.rdb —bytes 1024 -f memory.csv

將大于1024字節(jié)的 key 導(dǎo)出歼疮。然后進(jìn)行排序:

sort -t, -k4nr memory.csv |head -n 20杂抽,

終于找到了罪魁禍?zhǔn)住H缦聢D:

緊急刪除該 key 臨時(shí)解決了問(wèn)題韩脏,經(jīng)復(fù)盤發(fā)現(xiàn)缩麸,此問(wèn)題是開發(fā)時(shí)緩存使用不當(dāng),所有信息都不過(guò)期赡矢,數(shù)據(jù)只能越增越大杭朱。

總結(jié):緩存中放置的應(yīng)該是熱數(shù)據(jù),同時(shí)緩存策略也存在問(wèn)題济竹,應(yīng)該針對(duì)每條記錄設(shè)置不同的 key ,而不是都放在一個(gè) key 下霎槐。

案例二

某歷史項(xiàng)目最近總是報(bào)警(系統(tǒng)負(fù)載升高送浊,響應(yīng)變慢,應(yīng)用頻繁 GC )丘跌,只能頻繁重啟應(yīng)用袭景。分析 Dump 文件,發(fā)現(xiàn)創(chuàng)建的對(duì)象非常多闭树,但沒有明顯的占用大戶耸棒。于是繼續(xù)分析占用內(nèi)存較大的對(duì)象,發(fā)現(xiàn)都是 Hibernate 的代理對(duì)象报辱;接下來(lái)去看 Hibernate 的配置与殃,發(fā)現(xiàn)開啟了二級(jí)緩存,同時(shí) Ehcache 中沒有控制緩存對(duì)象的個(gè)數(shù)碍现,導(dǎo)致應(yīng)用啟動(dòng)一段時(shí)間后幅疼,隨著緩存對(duì)象的增多,很快會(huì)導(dǎo)致 GC 了昼接。于是我們緊急上線爽篷,關(guān)閉了部分對(duì)象的緩存,問(wèn)題得到了初步緩解慢睡。

總結(jié):當(dāng)使用本地緩存(如 Ehcache )時(shí)逐工,一定要嚴(yán)格控制緩存對(duì)象的個(gè)數(shù)及生命周期铡溪。由于 JVM 的特性,過(guò)多的緩存對(duì)象會(huì)極大的影響 JVM 性能泪喊。

案例三

某個(gè)正常運(yùn)行的應(yīng)用突然報(bào)警線程數(shù)高棕硫,之后很快就內(nèi)存溢出。查看日志發(fā)現(xiàn)無(wú)法連接 Memcached窘俺,繼而查看 Memcached 配置饲帅,發(fā)現(xiàn)連接數(shù)過(guò)高,拒絕連接瘤泪。而應(yīng)用連接 Memcached 的超時(shí)時(shí)間較長(zhǎng)灶泵,導(dǎo)致請(qǐng)求線程不斷堆積,最后應(yīng)用內(nèi)存溢出对途。臨時(shí)解決方案是先增加 Memcached 的連接數(shù)赦邻,之后應(yīng)用修改連接超時(shí)時(shí)間。

總結(jié):當(dāng)我們?cè)谑褂眠h(yuǎn)程緩存(如 Redis实檀、Memcached )時(shí)惶洲,一定要對(duì)超時(shí)時(shí)間進(jìn)行控制,一般來(lái)講緩存的總體響應(yīng)時(shí)間不能高于 50ms 膳犹,否則緩存會(huì)成為應(yīng)用的負(fù)擔(dān)恬吕,而不是幫手。

案例四

某項(xiàng)目關(guān)鍵業(yè)務(wù)忽然報(bào)警業(yè)務(wù)波動(dòng)须床,查看應(yīng)用日志發(fā)現(xiàn)訪問(wèn) Redis 異常铐料,查看 Redis 發(fā)現(xiàn)做了主備切換;這次超時(shí)時(shí)間設(shè)置沒問(wèn)題豺旬,但沒有針對(duì)緩存不可用做降級(jí)處理钠惩,導(dǎo)致業(yè)務(wù)流程中斷。

總結(jié):使用緩存時(shí)族阅,一定要有降級(jí)處理篓跛;尤其是關(guān)鍵業(yè)務(wù)環(huán)節(jié)。

案例五

某項(xiàng)目使用緩存后坦刀,開發(fā)測(cè)試沒問(wèn)題愧沟,上生產(chǎn)后,服務(wù)卻不可用鲤遥。查看日志發(fā)現(xiàn)是該應(yīng)用的緩存 key 與其他應(yīng)用緩存的 key 沖突央渣,導(dǎo)致錯(cuò)誤。

總結(jié):緩存使用時(shí)渴频,一定要有隔離的設(shè)計(jì)芽丹。比如 Redis 可以選擇不同的 DB,或者 Ehcache 定義不同的 Cache 名卜朗。如果這些都不方便實(shí)施拔第,至少也要有 key 的命名規(guī)范咕村,否則天知道會(huì)發(fā)生什么。

案例六

某項(xiàng)目使用 Redis 緩存臨時(shí)數(shù)據(jù)蚊俺,上線后出現(xiàn)錯(cuò)誤數(shù)據(jù)懈涛,但由于沒有開發(fā)管理功能,導(dǎo)致發(fā)生問(wèn)題時(shí)泳猬,看不到數(shù)據(jù)批钠,也無(wú)法管理,使得應(yīng)急時(shí)間較長(zhǎng)得封。

總結(jié):當(dāng)使用緩存后埋心,一定提供相應(yīng)的管理手段。否則發(fā)生事故時(shí)忙上,只能兩眼一抹黑拷呆。

案例七

某應(yīng)用在訪問(wèn)時(shí)經(jīng)常時(shí)快時(shí)慢,同時(shí) DB 負(fù)載也忽高忽低疫粥;分析代碼發(fā)現(xiàn)項(xiàng)目中緩存設(shè)置了一個(gè)固定的失效時(shí)間茬斧,當(dāng)緩存失效時(shí),會(huì)造成一段時(shí)間內(nèi)訪問(wèn) DB 的請(qǐng)求非常集中梗逮。

總結(jié):簡(jiǎn)單方案就是將緩存失效時(shí)間分散開项秉,比如我們可以將失效時(shí)間設(shè)置為一個(gè)區(qū)間內(nèi)的隨機(jī)值,這樣每一個(gè)緩存的過(guò)期時(shí)間的重復(fù)率就會(huì)降低慷彤,就很難引發(fā)集體失效的事件娄蔼。

案例八

某計(jì)費(fèi)項(xiàng)目發(fā)現(xiàn)計(jì)算結(jié)果有誤差,分析日志時(shí)發(fā)現(xiàn):系統(tǒng)修改規(guī)則后瞬欧,較長(zhǎng)時(shí)間仍在使用舊規(guī)則贷屎。查看 Ehcache 配置文件發(fā)現(xiàn)過(guò)期時(shí)間很長(zhǎng)罢防,導(dǎo)致規(guī)則更新后艘虎,很長(zhǎng)時(shí)間不生效,部分訂單計(jì)算費(fèi)用出現(xiàn)誤差咒吐。

總結(jié):使用本地緩存又需要數(shù)據(jù)一致性時(shí)野建,可以考慮用 Zookeeper 之類的協(xié)調(diào)服務(wù),實(shí)現(xiàn)一個(gè)更高效的緩存更新機(jī)制恬叹。

案例九

這是一個(gè)緩存穿透的案例候生,某模塊設(shè)計(jì)使用了緩存,但發(fā)現(xiàn)數(shù)據(jù)庫(kù)負(fù)載并沒有大幅下降绽昼。分析代碼發(fā)現(xiàn)唯鸭,緩存邏輯如下:數(shù)據(jù)庫(kù)存在紀(jì)錄則放到緩存中,不存在則下次仍然會(huì)訪問(wèn)數(shù)據(jù)庫(kù)硅确;導(dǎo)致不存在的訂單頻繁查詢時(shí)目溉,緩存沒有效果明肮。

總結(jié):緩存穿透是一個(gè)常見問(wèn)題,我們需要把 null 也作為一種緩存結(jié)果缭付,否則此類情況等于緩存是失效的柿估。

結(jié)尾

以上這些案例都是我們親身經(jīng)歷的血的教訓(xùn),在研發(fā)過(guò)程也是很容易忽略的點(diǎn)陷猫。誠(chéng)然使用緩存是提高應(yīng)用性能的有效手段秫舌,但沒有深入的分析與設(shè)計(jì)就很容易造成災(zāi)難性的影響。我思故我在绣檬,我們?cè)愁愖畲蟮膬?yōu)點(diǎn)就是思考能力足陨,希望這些小案例能引起大家更深層次的思考。另外河咽,軟件設(shè)計(jì)思想來(lái)源于生活钠右,比如看看 CPU 的設(shè)計(jì),有一級(jí)緩存忘蟹、二級(jí)緩存飒房,估計(jì)有很多小伙伴也在做緩存設(shè)計(jì)時(shí)這樣做了。生活中處處有設(shè)計(jì)媚值,只要用心總能觀察到狠毯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市褥芒,隨后出現(xiàn)的幾起案子嚼松,更是在濱河造成了極大的恐慌,老刑警劉巖锰扶,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件献酗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡坷牛,警方通過(guò)查閱死者的電腦和手機(jī)罕偎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)京闰,“玉大人颜及,你說(shuō)我怎么就攤上這事□彘梗” “怎么了俏站?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)痊土。 經(jīng)常有香客問(wèn)我肄扎,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任犯祠,我火速辦了婚禮萌丈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雷则。我一直安慰自己辆雾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布月劈。 她就那樣靜靜地躺著度迂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猜揪。 梳的紋絲不亂的頭發(fā)上惭墓,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音而姐,去河邊找鬼腊凶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拴念,可吹牛的內(nèi)容都是我干的钧萍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼政鼠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼风瘦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起公般,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤万搔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后官帘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞬雹,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年刽虹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酗捌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡状婶,死狀恐怖意敛,靈堂內(nèi)的尸體忽然破棺而出馅巷,到底是詐尸還是另有隱情膛虫,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布钓猬,位于F島的核電站稍刀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜账月,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一综膀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧局齿,春花似錦剧劝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至谣妻,卻和暖如春萄喳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蹋半。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工他巨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人减江。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓染突,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親辈灼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子觉痛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容