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