Redis+Guava的本地緩存組合

分類:└ 技術(shù)前沿,來源:江門深圳市巨鳥網絡科東劇技有限公司有限公司

前言

我們開發中(zhōng)經常用到 Redis慢務 作為緩存,将高頻數據放在 Redis 中(zhōng)能夠提高業(行工yè)務性能,降低 MySQL 等關(guān)系型數據庫壓力,甚至一些系統快裡使用 Redis 進行數據持久化,Redis子森 松散的文(wén)檔結構非常适合業(yè)務系統開發,在精确查詢,數購議據統計業(yè)務有着很大的優勢。
微信圖片_20220617075848.png

但是高頻數據流處理系統中(zhōng),Redis 的壓力也會很大,同時 I/O 開銷才是耗時的主要關明原因,這時候為了降低 Redis 讀寫壓力我們可(kě)以用到本地緩人山存,Guava 為我們提供了優秀的本地緩存 API,包含了過期策略等等,編碼難度低,個(gè)話坐人非常推薦。



設計示例

| Redis 懶加載緩存

數據在新增到 MySQL 不進行緩存,在精确靜信查找進行緩存,做到查詢即緩存,不查詢不緩存。


流程圖如(rú)下(xià):
Redis 懶加載緩存.png


代碼示例:
// 僞代碼示例 Xx代表你(nǐ)男窗的的業(yè)務對象 如(rú)User外但 Goods等等
public class&好習nbsp;XxLazyCache {

 &nbs下音p;  @Autowir謝票ed
    private&n這樹bsp;RedisTemplate redisTemplat北校e;

    美熱;@Autowired
 &n能可bsp;  private X暗黃xService xxService;//&nb音腦sp;你(nǐ)的業(yè)務service

&雨校nbsp;   /**
 &n地業bsp;   * 訊吧查詢 通(tōng)過查詢緩存外南是否存在驅動(dòng)緩存加載 建議在前置業(yè)務保證id風北對應數據是絕對存在于數據庫中(zhōng)的
  &睡了nbsp;  */
  &nbs和紙p; public Xx&nb制草sp;getXx(int id) {
&通服nbsp;   &n音還bsp;   // 討雨1.查詢緩存裡面有沒有數據
   對月    子信 Xx xxCache&n鐵飛bsp;= getXxFromCach市為e(id);
     &醫見nbsp;  if(xxCache 畫見;!= null) {
劇少    &nbs作這p;   &nbs聽來p;   return校制 xxCache;// 衛語男北句使代碼更有利于閱讀
  &nbs舞兵p;     }
&nb麗她sp;    &金女nbsp;  // 章技;2.查詢數據庫獲取數據 我們假定到業(yè)務這一步,傳冷要過來的id都在數據庫中(zhōng)有對應數街去據
   &如見nbsp;    Xx&nb相房sp;xx = xx作河Service.getXxById(id);
 &n動遠bsp;     &報電nbsp;// 3.設置緩存、這一步相當媽道于Redis緩存懶加載,下(xià)次再查詢此id,則會走緩存
&n好也bsp;    畫白;   setXxFromCache(xx);鄉城
    &n嗎黃bsp;   return&線媽nbsp;xx;
    也遠;    }家中
   &nb東林sp;}

    /短高**
    拍員 * 對xx數據進行修改或者删除操作 操作熱制數據庫成功後 删除緩存
 &n請答bsp;   *&n湖火bsp;删除請求 - 删除數據庫數據 工愛;删除緩存
     *姐內 修改請求 -&nb影靜sp;更新數據庫數據 删除緩存 下(xi訊多à)次在查詢時候就會從數據庫拉取新的數據到緩存中(zhōng)
&nb白電sp;    */
 &亮得nbsp;  public vo高弟id deleteXxFromCac麗還he(long id) {
  麗銀     &nb小個sp;String key = &書區quot;Xx:" + 科到xx.getId();
 &n文鄉bsp;   慢湖;   redi飛跳sTemplate.delete(key);
&n鐘器bsp;   }森電

   計窗 private void setXxFr木現omCache(Xx xx) 志月;{
    生村    String k錯飛ey = "Xx:&quo少時t; + xx.getId();
  放他     &nb民微sp;redisTemplate.opsFor鐘好Value().set(key, xx);
&n離慢bsp;   }

 &n男服bsp;  private Xx g可街etXxFromCache(int id)&nb裡影sp;{
    &nbs高線p;   //很雪 通(tōng)過緩存前綴拼裝唯一主鍵作為緩存Key 討但;如(rú)Xxx信息 就是Xxx:id
&nb東金sp;   相離    String&術信nbsp;key = "Xx:&qu間能ot; + id;
 &nb工年sp;    &nbs件的p; return re城她disTemplate.opsForValue大分().get(key);
  鐵資;  }

}
//&輛個nbsp;業(yè)務類
public&n是很bsp;class XxServie {
 爸湖;   @Autowired
 &看鐵nbsp;  private事外 XxLazyCache xxLazy對但Cache;
    /線自/ 查詢數據庫
   &nb理照sp;public Xx ge計市tXxById(long id) {
&n司場bsp;     &n房錯bsp; // 省略實現
 &你工nbsp;   &nbs麗睡p;  return xx;
&nbs看歌p;   }

  件紙;  public void&n到了bsp;updateXx(Xx 家站;xx) {
    &n來在bsp;  &nbs是吧p;// 更新MySQL數據 省略
 飛件    &nb我間sp;  // 删除緩存
 &知高nbsp;   &nbs家道p;  xxLazyCache.del遠玩eteXxFromCache(xx.getId());
&nb大樂sp;   }

做大   &n火哥bsp;public void deleteXx(麗舊long id) {
  &nbs船習p;     //&n嗎影bsp;删除MySQL數據 省略
  &間海nbsp;    &nbs生什p;// 删除緩存
 &北科nbsp;   &現下nbsp;  xxLazyCache.dele媽樂teXxFromCache(xx.getId());
 &nb水會sp;  }
}
// 實體歌書類
@Data
public c黃銀lass Xx {
   老技; // 業(yè)道影務主鍵
    pri嗎一vate Long id;
  會熱;  // ...省略
}

優點如(rú)下(xià):

  • 保證最小的緩存量滿足精确查詢業(yè)務,避免冷(lěng)現友數據占用寶貴的内存空間
  • 對增删改查業(yè)務入侵小、删除即同步
  • 可(kě)插拔,對于老系統升級,曆史數據無需在啟動(dòng)時初始化呢裡緩存


缺點如(rú)下(xià):

  • 數據量需可(kě)控,在無限增長業(yè章來)務場景不适用
  • 在微服務場景不利于全局緩存應用


總結:

  • 空間最小化
  • 滿足精确查詢場景
  • 總數據量可(kě)控推薦使用
  • 微服務場景不适用


| Redis 結合本地緩存

微服務場景下(xià),多個(gè)微服務使用一個(gè)大緩存,流數火在據業(yè)務下(xià),高頻讀取緩存對拿家 Redis 壓力很大,我們使用本地緩存結合 Redis 緩存使用,降低 Redis 壓力信跳,同時本地緩存沒有連接開銷,性能更優。



流程圖如(rú)下(xià):
Redis 結合本地緩存.png


業(yè)務場景:在流處數處理過程中(zhōng),微服務對多個(gè)設備上傳的數司歌據進行處理,每個(gè)設備有一個(gè) code,流數據的頻率高,在消息靜討隊列發送過程中(zhōng)使用分區發送,我們需要為設備 c街爸ode 生成對應的自增号,用自增号對 kafka 中(zhōng) to秒紙pic 分區數進行取模。


這樣如(rú)果有 10000 台設備,自增号就是 0愛吧~9999,在取模後就進行分區發送就可(kě)以做到每個地醫(gè)分區均勻分布。


這個(gè)自增号我們使用 redis 的自增數生成,生成後鐘車放到 redis 的 hash 結構進行緩存,每次來一個(gè)設備,員服我們就去這個(gè) hash 緩存中(zhōng)取,沒雪新有取到就使用自增數生成一個(gè),然後放到 redis 的 hash 緩工笑存中(zhōng)。


這時候每個(gè)設備的自增數一經生成是不站農會再發生改變的,我們就想到使用本地緩存進行優化,避免高頻的調用 redis 制爸去獲取,降低 redis 壓力。



代碼示例:
/** * 此緩存演遠微示如(rú)何結合redis自增數 hash 本地緩存使用劇南進行設備自增數的生成、緩存、本地緩存 * 本地村東緩存使用Guava Cache */public日土 class DeviceIncCa海近che {   愛短; /**    &n分術bsp;* 本地緩存  &n銀志bsp;  */ &n技用bsp;  private&nb媽照sp;Cache



優點如(rú)下(xià):

  • redis 保證數據可(kě)持久,本地緩存保證超高的讀取性能,內南微服務共用 redis 大緩存的場景能有效降低 redis 壓力
  • guava 作為本地緩存,提供了豐富的 api,過期策略,最大容量分年,保證服務内存可(kě)控,冷(lěng)數據不會長服我期占據内存空間
  • 服務重啟導緻的本地緩存清空不會影響業(yè)什錯務進行
  • 微服務及分布式場景使用,分布式情況下(xià)每個(錢月gè)服務實例隻會緩存自己接入的那一部分設備的自增号,本地内存空間最優
  • 在示例業(yè)務中(zhōng),自增數滿足要家了分布區發送的均勻分布需求,也可(kě)以滿足統計設備接入數目的業(yè)務林筆場景,一舉兩得


缺點如(rú)下(xià):

  • 增加編碼複雜度,不直接
  • 隻适用于緩存内容隻增不改的場景


總結:

  • 本地緩存空間可(kě)控,過期策略優
  • 适用于微服務及分布式場景
  • 緩存内容不能發生改變
  • 性能優




後記

redis 提供了豐富的數據類型及api,非常适合業(yè)務系統開發,統計計數(increment,dec機些rement),标記位(bitmap),松散數據(ha美作sh),先進先出、隊列式讀取(list)。訊吧


guava 緩存作為本地緩存,能夠高效的讀取的同時,提供了大量 a日很pi 方便我們控制本地緩存的數據量及冷(lěng)數據淘汰。


我們充分的學習這些特性能夠幫助我們在業(yè)務開發中(zhōng)更加輕女一松靈活,在空間與時間上找到一個(gè)平衡點。