日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

架构设计 | 缓存管理模式,监控和内存回收策略

發(fā)布時間:2025/3/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 架构设计 | 缓存管理模式,监控和内存回收策略 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文源碼:GitHub·點這里 || GitEE·點這里

一、緩存設(shè)計

1、緩存的作用

在業(yè)務(wù)系統(tǒng)中,查詢時最容易出現(xiàn)性能問題的模塊,查詢面對的數(shù)據(jù)量大,篩選條件復(fù)雜,所以在系統(tǒng)架構(gòu)中引入緩存層,則是非常必要的,用來緩存熱點數(shù)據(jù),達(dá)到快速響應(yīng)的目的。

緩存使用的基本原則:

  • 所有緩存數(shù)據(jù),必須設(shè)置過期時間;
  • 核心業(yè)務(wù)流程不通過緩存層;
  • 緩存層移除,不影響現(xiàn)有流程;
  • 系統(tǒng)各個端首頁數(shù)據(jù)不實時查詢;
  • 報表數(shù)據(jù)不實時查詢加載;
  • 歸檔數(shù)據(jù)(定時統(tǒng)計的結(jié)果數(shù)據(jù))不實時查詢;

這里是業(yè)務(wù)架構(gòu)中常用的緩存策略,緩存通過犧牲強(qiáng)一致性來提高性能,所以并不是所有的業(yè)務(wù)都適合用緩存,實際考量都會針對具體的業(yè)務(wù),比如用戶相關(guān)維度的數(shù)據(jù)修改頻率低,會使用緩存,但是用戶權(quán)限數(shù)據(jù)(比如:免費次數(shù))會考慮實時校驗,緩存層使用的相對較少。

2、緩存設(shè)計模式

Cache-Aside模式

業(yè)務(wù)中最常用的緩存層設(shè)計模式,基本實現(xiàn)邏輯和相關(guān)概念如下:

  • 緩存命中:直接查詢緩存且命中,返回數(shù)據(jù);
  • 緩存加載:查詢緩存未命中,從數(shù)據(jù)庫中查詢數(shù)據(jù),獲取數(shù)據(jù)后并加載到緩存;
  • 緩存失效:數(shù)據(jù)更新寫到數(shù)據(jù)庫,操作成功后,讓緩存失效,查詢時候再重新加載;
  • 緩存穿透:查詢數(shù)據(jù)庫不存在的對象,也就不存在緩存層的命中;
  • 緩存擊穿:熱點key在失效的瞬間,高并發(fā)查詢這個key,擊穿緩存,直接請求數(shù)據(jù)庫;
  • 緩存雪崩:緩存Key大批量到過期時間,導(dǎo)致數(shù)據(jù)庫壓力過大;
  • 命中率:緩存設(shè)計的是否合理要看命中率,命中率高說明緩存有效抗住了大部分請求,命中率可以通過Redis監(jiān)控信息計算,一般來說命中率在(70-80)%都算合理。
    并發(fā)問題

執(zhí)行讀操作未命中緩存,然后查詢數(shù)據(jù)庫中取數(shù)據(jù),數(shù)據(jù)已經(jīng)查詢到還沒放入緩存,同時一個更新寫操作讓緩存失效,然后讀操作再把查詢到數(shù)據(jù)加載緩存,導(dǎo)致緩存的臟數(shù)據(jù)。

在遵守緩存使用原則下出現(xiàn)該情況概率非常低,可以通過復(fù)雜的Paxos協(xié)議保證一致性,一般情況是不考量該場景的處理,如果緩存管理過于復(fù)雜,會和緩存層核心理念相悖。

基本描述代碼:

@Service public class KeyValueServiceImpl extends ServiceImpl<KeyValueMapper, KeyValueEntity> implements KeyValueService {@Resourceprivate RedisService redisService ;@Overridepublic KeyValueEntity select(Integer id) {// 查詢緩存String redisKey = RedisKeyUtil.getObectKey(id) ;String value = redisService.get(redisKey) ;if (!StringUtils.isEmpty(value) && !value.equals("null")){return JSON.parseObject(value,KeyValueEntity.class);}// 查詢庫KeyValueEntity keyValueEntity = this.getById(id) ;if (keyValueEntity != null){// 緩存寫入redisService.set(redisKey,JSON.toJSONString(keyValueEntity)) ;}// 返回值return keyValueEntity ;}@Overridepublic boolean update(KeyValueEntity keyValueEntity) {// 更新數(shù)據(jù)boolean updateFlag = this.updateById(keyValueEntity) ;// 清除緩存if (updateFlag){redisService.delete(RedisKeyUtil.getObectKey(keyValueEntity.getId()));}return updateFlag ;} }

Read-Throug模式

當(dāng)應(yīng)用系統(tǒng)向緩存系統(tǒng)請求數(shù)據(jù)時,如果緩存中并沒有對應(yīng)的數(shù)據(jù)存在,緩存系統(tǒng)將向底層數(shù)據(jù)源的讀取數(shù)據(jù)。如果數(shù)據(jù)在緩存中存在,則直接返回緩存中存在的數(shù)據(jù)。把更新數(shù)據(jù)庫的操作由緩存層代勞了。

Write-Through模式

更新寫數(shù)據(jù)時,如果沒有命中緩存,則直接更新數(shù)據(jù)庫,如果命中了緩存,則先更新緩存,然后由緩存系統(tǒng)自行更新數(shù)據(jù)庫。

Write-Behind模式

應(yīng)用系統(tǒng)對緩存中的數(shù)據(jù)進(jìn)行更新時,只更新緩存,不更新數(shù)據(jù)庫,緩存系統(tǒng)會異步批量向底層數(shù)據(jù)源更新數(shù)據(jù)。

二、數(shù)據(jù)一致問題

業(yè)務(wù)開發(fā)模式中,會涉及到一個問題:如何最大限度保證數(shù)據(jù)庫和Redis緩存的數(shù)據(jù)一致性?

首先說明一下:數(shù)據(jù)庫和緩存強(qiáng)一致性同步成本太高,如果追求強(qiáng)一致,緩存層存在的價值就會很低,如上緩存模式一中幾乎可以解決大部分業(yè)務(wù)場景問題。

解決這個問題的方式很多:

方案一說明:

  • 數(shù)據(jù)庫更新寫入數(shù)據(jù)成功;
  • 準(zhǔn)備一個先進(jìn)先出模式的消息隊列;
  • 把更新的數(shù)據(jù)包裝為一個消息放入隊列;
  • 基于消息消費服務(wù)更新Redis緩存;

分析:消息隊列的穩(wěn)定和可靠性,操作層面數(shù)據(jù)庫和緩存層解耦。

方案二說明:

  • 提供一個數(shù)據(jù)庫Binlog訂閱服務(wù),并解析修改日志;
  • 服務(wù)獲取修改數(shù)據(jù),并向Redis服務(wù)發(fā)送消息;
  • Redis數(shù)據(jù)進(jìn)行修改,類似MySQL的主從同步機(jī)制;

分析:系統(tǒng)架構(gòu)層面多出一個服務(wù),且需要解析MySQL日志,操作難度較大,但流程上更為合理。

總結(jié)描述

分布式架構(gòu)中,緩存層面的基本需求就是提高響應(yīng)速度,不斷優(yōu)化,追求數(shù)據(jù)庫和Redis緩存的數(shù)據(jù)快速一致性,從提供的各種方案中都可以看出,這也在增加緩存層面處理的復(fù)雜性,架構(gòu)邏輯復(fù)雜,就容易導(dǎo)致程序錯誤,所以針對業(yè)務(wù)選擇合理的處理邏輯,這點很關(guān)鍵。

三、緩存監(jiān)控

1、Redis服務(wù)監(jiān)控

通過info命令查看Redis服務(wù)的參數(shù)信息,可以通過傳參查看指定分類配置。通過config…set設(shè)置具體配置參數(shù)。例如:

@Override public Properties info(String var) {if (StringUtils.isEmpty(var)){return redisTemplate.getRequiredConnectionFactory().getConnection().info();}return redisTemplate.getRequiredConnectionFactory().getConnection().info(var); }

傳參說明:

  • memory:內(nèi)存消耗相關(guān)信息
  • server:有關(guān)Redis服務(wù)器的常規(guī)信息
  • clients:客戶端連接部分
  • stats:一般統(tǒng)計
  • cpu:CPU消耗統(tǒng)計信息

應(yīng)用案例:

@RestController public class MonitorController {@Resourceprivate RedisService redisService ;private static final String[] monitorParam = new String[]{"memory","server","clients","stats","cpu"} ;@GetMapping("/monitor")public List<MonitorEntity> monitor (){List<MonitorEntity> monitorEntityList = new ArrayList<>() ;for (String param:monitorParam){Properties properties = redisService.info(param) ;MonitorEntity monitorEntity = new MonitorEntity () ;monitorEntity.setMonitorParam(param);monitorEntity.setProperties(properties);monitorEntityList.add(monitorEntity);}return monitorEntityList ;}}

通過上述參數(shù)組合,把Redis相關(guān)配置參數(shù)打印出來,然后可視化輸出,儼然一副高端的感覺。

配置參數(shù)說明:

這里只對兩個參數(shù)說明一下,計算命中率的關(guān)鍵信息:

  • keyspace_misses:查找緩存Key失敗的次數(shù);
  • keyspace_hits:查找緩存Key命中的次數(shù);

公式:命中率=命中次數(shù)/(hits+misses)查找總次數(shù)。

2、LRU算法說明

Redis的數(shù)據(jù)是放在內(nèi)存中的,所以速度快,自然也就受到內(nèi)存大小的限制,如果內(nèi)存使用超過配置,Redis有不同的回收處理策略。

內(nèi)存模塊參數(shù):maxmemory_policy

  • noenviction:不回收數(shù)據(jù),查詢直接返回錯誤,但可以執(zhí)行刪除;
  • allkeys-lru:從所有的數(shù)據(jù)中挑選最近最少使用的數(shù)據(jù)淘汰;
  • volatile-lru:已設(shè)置過期時間的數(shù)據(jù)中挑選最近最少使用的數(shù)據(jù)淘汰;
  • allkeys-random:從所有數(shù)據(jù)中任意選擇數(shù)據(jù)淘汰;
  • volatile-random:從已設(shè)置過期時間的數(shù)據(jù)中任意選擇數(shù)據(jù)淘汰;
  • volatile-ttl:從已設(shè)置過期時間的數(shù)據(jù)中挑選將要過期的數(shù)據(jù)淘汰;

大部分情況下,業(yè)務(wù)都是希望最熱點數(shù)據(jù)可以被緩存,所以相對使用allkeys-lru策略偏多。這里要根據(jù)業(yè)務(wù)模式特點衡量。

四、源代碼地址

GitHub·地址 https://github.com/cicadasmile/data-manage-parent GitEE·地址 https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:《架構(gòu)設(shè)計系列》,蘿卜青菜,各有所需

序號標(biāo)題
01架構(gòu)基礎(chǔ):單服務(wù).集群.分布式,基本區(qū)別和聯(lián)系
02架構(gòu)設(shè)計:分布式業(yè)務(wù)系統(tǒng)中,全局ID生成策略
03架構(gòu)設(shè)計:分布式系統(tǒng)調(diào)度,Zookeeper集群化管理
04架構(gòu)設(shè)計:接口冪等性原則,防重復(fù)提交Token管理

總結(jié)

以上是生活随笔為你收集整理的架构设计 | 缓存管理模式,监控和内存回收策略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。