資料內(nèi)容:
一、第一個(gè)緩存組件的開(kāi)發(fā)
1、開(kāi)發(fā)背景
2020 圣誕節(jié)前后業(yè)務(wù)流量受疫情恢復(fù)開(kāi)始反彈,增值業(yè)務(wù)系統(tǒng) db 的 qps 單庫(kù)上漲至 3 萬(wàn)以上,核心
接口延遲增加,增值業(yè)務(wù)交易系統(tǒng) load 節(jié)節(jié)升高,生單存在性能安全隱患。
經(jīng)調(diào)查發(fā)現(xiàn):
大量請(qǐng)求處在 IO 阻塞中且系統(tǒng)線程數(shù)(2000+)和活動(dòng)線程過(guò)高,系統(tǒng)上下文切換開(kāi)銷大。
為此,我們團(tuán)隊(duì)做了很多性能優(yōu)化的措施,其中最重要一個(gè)動(dòng)作就是給數(shù)據(jù)庫(kù)層加了一個(gè)特殊的緩存方
案,這個(gè)緩存方案就是我們開(kāi)發(fā)的第一個(gè)緩存組件。
之前系統(tǒng)已有在用redis和guava緩存的,為什么這次還要再加一個(gè)針對(duì) db 層的緩存方案呢?主要源于
以下幾點(diǎn):
本次性能問(wèn)題突出在 db 上,db 的連接過(guò)高也在報(bào)警。
系統(tǒng)體量是很大的,僅交易系統(tǒng)有 30 萬(wàn)以上代碼,系統(tǒng)內(nèi)部流程和分支很多,直接在入口處做緩
存命中率不會(huì)很高,而系統(tǒng)最關(guān)鍵表結(jié)構(gòu)只有 6 個(gè),在此處做緩存更好收口。
這是個(gè)迭代過(guò)多年的系統(tǒng),內(nèi)部流程很長(zhǎng),上下文間經(jīng)常有些對(duì) db 重復(fù)的查詢,改業(yè)務(wù)流程工作
量大需要回歸的 case 太多。
交易系統(tǒng)對(duì)緩存的一致性要求極高,需要專用的緩存方案。除此之外,傳統(tǒng)的與數(shù)據(jù)庫(kù)有關(guān)的緩存方案在我們的業(yè)務(wù)場(chǎng)景 下是存在缺限的:
mysql 數(shù)據(jù)庫(kù)端的查詢緩存,這個(gè)緩存很雞肋,只要數(shù)據(jù)發(fā)生變更相關(guān)緩存數(shù)據(jù)全部失效,對(duì)于
一個(gè)含訂單交易的系統(tǒng)而言變更可是常態(tài)。
mybatis 二級(jí)存在,不僅一致性較差,其緩存粒度是基于 mapper , 一條數(shù)據(jù)的變更會(huì)將整個(gè)
mapper 的緩存數(shù)據(jù)清空。
使用 aop 和注解,基于方法直接在 dao 請(qǐng)求和 mysql 間加一個(gè) redis ,這個(gè)如果沒(méi)有更細(xì)節(jié)的設(shè)
計(jì),分布式環(huán)境下的全局一致性是得不到保證的。
基于 binglog 同步做緩存,這個(gè)是有秒級(jí)內(nèi)延遲的,不適用于交易系統(tǒng)。
2、設(shè)計(jì)思考
我們?cè)O(shè)計(jì)的這個(gè)緩存組件命名為 daoCache ,原于其加在 dao 層上,其主作用于分擔(dān)數(shù)據(jù)庫(kù)的 qps ,
以近 1:1 的比例將 mysql 的查詢請(qǐng)求轉(zhuǎn)移至 redis ,通過(guò)一套固化的流程和機(jī)制確保在分布式環(huán)境下
緩存數(shù)據(jù)與 db 具有較高一致性,同時(shí)盡可能對(duì)業(yè)務(wù)使用透明。
分布式場(chǎng)景的一致性理論基礎(chǔ) cap 原則和 base 理論告訴我們?cè)诜植际江h(huán)境下無(wú)法在強(qiáng)一致性上去死
磕,分布式緩存完整的強(qiáng)制一致是一個(gè)不可解的問(wèn)題, 工程實(shí)踐時(shí)應(yīng)主要考慮一致性、開(kāi)發(fā)成本與性能
開(kāi)銷之間的平衡。由于這是一個(gè)重要的緩存方案,為了降低實(shí)踐風(fēng)險(xiǎn),我們做了充分的分析和思考。