效率

同一次業(yè)務(wù)操作過程中,往往會(huì)出現(xiàn)某種操作被重復(fù)執(zhí)行,邏輯上來講如果只執(zhí)行一次是最理想的。這里所指的操作特指一些IO操作,比如從數(shù)據(jù)庫(kù)中獲取登錄人的信息,也就是說如果一次請(qǐng)求中包含5個(gè)小邏輯,這5個(gè)小邏輯包含3次獲取用戶信息的操作,理想的情況是3次只有一次是從數(shù)據(jù)庫(kù)中加載,其余的兩次從緩存中獲取。

  • 多次調(diào)用,每個(gè)服務(wù)實(shí)現(xiàn)獨(dú)自請(qǐng)求用戶信息。

     

  • 一次調(diào)用,多次讀取。首先從Context中加載,如果失敗從數(shù)據(jù)庫(kù)中加載,最后將結(jié)果存入Context。

前提

限于非web環(huán)境,這里是dubbo實(shí)現(xiàn)的微服務(wù)。如果是web環(huán)境的話解決問題比較簡(jiǎn)單,因?yàn)槲覀兛梢猿浞掷肧pring Framwork中提到的三個(gè)bean生命周期的特殊來解決:

  • request
  • session
  • global

案例

將老的價(jià)格數(shù)據(jù)遷移成新的價(jià)格數(shù)據(jù),這里大概是如下的步驟:

  • 刪除新老價(jià)格的關(guān)系,因?yàn)樾枰С种貜?fù)遷移
  • 禁用之前已經(jīng)存在的價(jià)格規(guī)則,規(guī)則是描述價(jià)格在某種場(chǎng)景下生效的邏輯
  • 創(chuàng)建新的價(jià)格
  • 創(chuàng)建新的規(guī)則
  • 啟用新規(guī)則

上面步驟的價(jià)格,規(guī)則,關(guān)系數(shù)據(jù)分別屬于三個(gè)業(yè)務(wù)對(duì)象,自身都具備CRUD的服務(wù)接口,這些CRUD都需要記錄操作人信息,記錄的標(biāo)準(zhǔn)就是接口傳入的操作人所持有的token,我們需要將這個(gè)token轉(zhuǎn)換成userId,userName之類的信息與價(jià)格,規(guī)則等信息一并存儲(chǔ)。

時(shí)序圖如下:

問題:遷移一條價(jià)格多次讀取用戶信息效率低

由于遷移價(jià)格會(huì)涉及到多個(gè)對(duì)象的操作,而操作這些具體業(yè)務(wù)對(duì)象的接口并不支持傳具體的userId,userName只支持token,所以不可避免的會(huì)在保存價(jià)格等信息時(shí)各自去根據(jù)token查詢操作人信息。實(shí)測(cè)一個(gè)價(jià)格完成一次數(shù)據(jù)遷移涉及到獲取用戶信息的次數(shù)多達(dá)20+次,效率是比較低,如何去解決呢?

現(xiàn)狀

由于我目前實(shí)現(xiàn)的微服務(wù)是無狀態(tài)的,也不是web環(huán)境,所以上面提到的那些bean的作用域功能就使用不上。

目標(biāo)

實(shí)現(xiàn)類似request作用域的功能,一次請(qǐng)求僅執(zhí)行一次,其余的請(qǐng)求從緩存中獲取結(jié)果以提高IO操作效率。

方案

可采用TreadLocal來當(dāng)緩存,存儲(chǔ)頻繁讀取的數(shù)據(jù)。增加了CacheContext,獲取用戶首先從CacheContext中取,如果為空則從數(shù)據(jù)庫(kù)加載然后回寫到Treadlocal中,下一次再請(qǐng)求用戶信息時(shí)就可以命中緩

網(wǎng)友評(píng)論