應(yīng)用層緩存 VS ORM緩存
最近做一個(gè)比較大的電子商務(wù)項(xiàng)目,預(yù)計(jì)每天訂單量將在5萬(wàn)多單,客服人員需要頻繁的下單、查詢訂單、操作訂單,客人預(yù)訂完訂單后,會(huì)立即進(jìn)入處理流程,為了提高服務(wù)質(zhì)量,要求流水化作業(yè),平均要在40分鐘-80分鐘內(nèi)處理完訂單。所以訂單在創(chuàng)建后,會(huì)在短時(shí)間內(nèi),被頻繁的修改和查看。
由于在項(xiàng)目中ORM層主要是基于Hibernate框架,所以在調(diào)優(yōu)時(shí),很自然的就想到打開(kāi)Hibernate的二級(jí)緩存,以次來(lái)減小由于Load 訂單大對(duì)象時(shí)N+1次查詢給數(shù)據(jù)造成的壓力,自己做的測(cè)試效果也非常好,也順利通過(guò)壓力測(cè)試。
但在上線時(shí),性能卻并不佳,經(jīng)過(guò)分析業(yè)務(wù)的操作特點(diǎn),查找原因有以下幾占:,
??? 1.但由于中臺(tái)每天在工作當(dāng)中,頻繁的批量分配工單,
???
??? 因?yàn)橐繉⒂唵畏峙浣o某一個(gè)工作人員處理,在代碼當(dāng)中執(zhí)行了一個(gè)bulkUpdate的操作:
template.bulkUpdate("update order set owner = ? where id in (?, ?,?)");
???
??? 這時(shí)Hibernate會(huì)直接將Order對(duì)象的二級(jí)緩存清楚掉。
??? 由于二級(jí)緩存,總是被刷掉,再查詢時(shí),需要重新從數(shù)據(jù)庫(kù)Load,所以二級(jí)緩存變相直接起的作用很少。
??? 2.由于工作人員在處理訂單時(shí),每一次查看之后,都有更新操作,在更新之后,訂單被清除緩存,下一組人在處理訂單時(shí),又得重新LOAD,所以效果并不好。
??? 3.無(wú)論是白盒測(cè)試,還是壓力測(cè)試時(shí),所基于的案例太過(guò)于簡(jiǎn)單,沒(méi)有更深入的模仿業(yè)務(wù)操作,對(duì)于壓力測(cè)試的腳本,也很難精確的模擬出真實(shí)的流程化的業(yè)務(wù)操作過(guò)程。
??? 開(kāi)始想到,直接獲得Session,直接使用JDBC來(lái)編寫(xiě)更新代碼,并在更新后,使用sessionFactory.evict(Order.class, id);來(lái)有目標(biāo)的逐個(gè)清除特定的對(duì)象,以避免全部清楚緩存。
??? 但樣做,會(huì)對(duì)DAO層,修改過(guò)大。
??? 由于整個(gè)模塊最核心的商業(yè)對(duì)象就是訂單,最后決定在Service層對(duì)訂單開(kāi)小灶,對(duì)訂單緩存的單獨(dú)的定制處理。
??? 我覺(jué)得應(yīng)用緩存存在以下優(yōu)點(diǎn):
??? 1。速度要快于ORM緩存,
??? 2。對(duì)于緩存的控制權(quán)更大,可以直接控制緩存工具的API進(jìn)行操作,可以避免一些盲目清除的操作。
??? 3。更靈活的控制緩存中對(duì)象的失效,如根據(jù)事件來(lái)清除緩存,如訂單的處理流程結(jié)束時(shí),將該訂單從緩存中清除掉,
??? 4。在更新數(shù)據(jù)庫(kù)時(shí),不是直接清除緩存,而是更新緩存(盡管這有風(fēng)險(xiǎn)),當(dāng)業(yè)務(wù)層拋出異常時(shí),才去清空緩存,避免由于頻繁更新,而清空緩存。
?? 缺點(diǎn):
?? 1。訂單的更新操作,必須是單點(diǎn)的,只能通過(guò)IOrderService提供的接口,進(jìn)行更新操作,否則數(shù)據(jù)不一致的風(fēng)險(xiǎn)較大。
?? 2。有一定的代碼工作量
?? 3。如果不對(duì)第三方緩存包,進(jìn)行一定的封裝的話,會(huì)直接耦合于第三方的緩存包,不能像Hibernate那樣,靈活選擇和配置緩存工具。不容易達(dá)到ORM緩存最強(qiáng)大的那種透明化和靈活可配置,你可以使用Ehcache, 也可以選Jboss,有錢(qián)的話,可以用Tangosol。
?? 4。對(duì)業(yè)務(wù)層代碼有一定的侵入
???
??? 目前的方案是采用應(yīng)用層的現(xiàn)代化,同時(shí)使用如Proxy模式來(lái)提供透明化的設(shè)計(jì),
??? IOrderService -》? OrderService -》 CacheableOrderService
??? 通過(guò)Spring的Bean配置,一樣可以實(shí)現(xiàn)透明化的操作。
?? 結(jié)論:
?? 1。緩存的清空與更新,要盡量精確的去操作受到更新影響的對(duì)象,而不是全部搞掉。
?? 在Hibernate當(dāng)中,也提供了sessionFactory.evict(class, id)這樣細(xì)粒度的清空緩存對(duì)象的方法。
????????? sessionFactory.evice(class)的操作,要看這樣的操作是否頻繁,如果頻繁,對(duì)于緩存的作用就會(huì)大大的折扣。
2。如果緩存對(duì)象過(guò)多,對(duì)于失效的算法與處理,要與業(yè)務(wù)對(duì)象的特性緊密的聯(lián)合起來(lái),通過(guò)事件來(lái)驅(qū)動(dòng)對(duì)象的失效。
3。對(duì)于商業(yè)對(duì)象的緩存,必須要深刻分析對(duì)象的生命周期,業(yè)務(wù)特性。
4。對(duì)于數(shù)據(jù)不一致的風(fēng)險(xiǎn),要有足夠的認(rèn)識(shí)與預(yù)防手段。
5。合理的估計(jì)訂單對(duì)象的大小,分配足夠的內(nèi)存
6。如果只使用中心緩存,只能減小數(shù)據(jù)庫(kù)的壓力,對(duì)于網(wǎng)絡(luò)帶寬的壓力,還是有的,速度上也遠(yuǎn)遠(yuǎn)遜于本地緩存的效果,所以要結(jié)合本地緩存+中心緩存的策略方案,即提高速度,避免群集復(fù)制時(shí)的瓶頸。
posted on 2007-06-02 19:39 Speed 閱讀(2992) 評(píng)論(4) 編輯 收藏 所屬分類: 框架設(shè)計(jì) 、J2EE