最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis?原生二級(jí)緩存"難以修復(fù)"的原因解析及解決方案

 更新時(shí)間:2025年12月04日 10:28:42   作者:曠野說  
文章主要討論了MyBatis原生二級(jí)緩存存在的問題,包括結(jié)構(gòu)性缺陷、難以修復(fù)等,社區(qū)提供了多種增強(qiáng)插件方案,但這些方案也有各自的優(yōu)缺點(diǎn),本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

?? 一、為什么 MyBatis 原生二級(jí)緩存“難以修復(fù)”?

MyBatis 二級(jí)緩存的底層設(shè)計(jì)存在結(jié)構(gòu)性缺陷,不是加個(gè)插件就能完美解決的:

問題原因高并發(fā)影響
緩存 Key 粒度粗糙Key = namespace + sql + params,但 params 是對(duì)象哈希,分頁/排序等參數(shù)容易哈希沖突或忽略語義差異返回錯(cuò)誤數(shù)據(jù)(如分頁錯(cuò)亂)
無 TTL / 過期機(jī)制默認(rèn)使用 PerpetualCache,數(shù)據(jù)永不過期內(nèi)存泄漏 + 臟讀
跨 JVM 無法共享緩存是本地內(nèi)存(JVM 內(nèi)),多實(shí)例部署時(shí)各節(jié)點(diǎn)緩存不一致數(shù)據(jù)分裂,用戶看到不同結(jié)果
寫操作不自動(dòng)失效關(guān)聯(lián)緩存更新 User 表,不會(huì)自動(dòng)清理 OrderMapper 中關(guān)聯(lián)的 user_orders 緩存臟讀持續(xù)存在

?? 這些是架構(gòu)級(jí)缺陷,靠攔截器或裝飾器插件無法根本解決。

?? 二、社區(qū)增強(qiáng)插件方案(可選,但需謹(jǐn)慎)

雖然不能“修復(fù)”,但有插件替換緩存實(shí)現(xiàn),提升可用性:

1.mybatis-redis(最常用)

@Mapper
@CacheNamespace(implementation = RedisCache.class)
public interface OrderMapper {
    // ...
}
  • ? 優(yōu)點(diǎn):跨實(shí)例一致、可設(shè) TTL(需自定義)
  • ? 缺點(diǎn):
    • 無法解決 Key 語義問題(分頁/動(dòng)態(tài) SQL 緩存 key 仍可能沖突)
    • 每次查詢都多一次 Redis 網(wǎng)絡(luò) IO,在 10w QPS 下可能成為瓶頸
    • 序列化成本高(Java 對(duì)象需序列化為 byte[])

?? 適用場景:讀多寫少、數(shù)據(jù)變更不頻繁、對(duì)延遲不敏感的配置類數(shù)據(jù)(如字典表)

2.自定義 Cache 實(shí)現(xiàn)(繼承 MyBatisCache接口)

你可以自己實(shí)現(xiàn)帶版本號(hào)邏輯過期的緩存:

public class VersionedCache implements Cache {
    private final String id;
    private final RedisTemplate redis;
    @Override
    public void putObject(Object key, Object value) {
        // key = "order:123", value = { data: {...}, version: 20251203 }
        redis.opsForHash().put("mybatis:cache:" + id, serialize(key), wrapWithVersion(value));
    }
    @Override
    public Object getObject(Object key) {
        Object cached = redis.opsForHash().get("mybatis:cache:" + id, serialize(key));
        if (cached != null && isVersionValid(cached)) {
            return unwrap(cached);
        }
        return null;
    }
}
  • ? 優(yōu)點(diǎn):可控制緩存結(jié)構(gòu)、加版本、加 TTL
  • ? 缺點(diǎn):開發(fā)維護(hù)成本高,且仍受限于 MyBatis 緩存 key 生成邏輯

?? 三、我們的選擇:棄用二級(jí)緩存,自建業(yè)務(wù)緩存層

在高并發(fā)訂單系統(tǒng)中,我們最終徹底關(guān)閉 MyBatis 二級(jí)緩存,原因如下:

  1. 控制權(quán)不足:MyBatis 緩存是“黑盒”,無法插入降級(jí)、熔斷、監(jiān)控邏輯
  2. 異常難追溯:緩存臟數(shù)據(jù)問題往往延遲暴露,修復(fù)成本高
  3. 違背“可觀測性”原則:緩存命中/失效無法對(duì)接 Prometheus / SkyWalking

? 替代方案:業(yè)務(wù)層 + Redis + 冪等 + 版本號(hào)

@Service
public class OrderService {
    public Order getOrder(Long id) {
        String cacheKey = "order:v2:" + id;
        Order order = redis.get(cacheKey, Order.class);
        if (order != null) return order;
        // 雙檢鎖 + 空值緩存防穿透
        synchronized (getLockKey(id)) {
            order = redis.get(cacheKey, Order.class);
            if (order == null) {
                order = orderMapper.findById(id);
                if (order != null) {
                    redis.setex(cacheKey, 300, order); // 5分鐘過期
                } else {
                    redis.setex("empty:" + cacheKey, 60, "1"); // 防緩存穿透
                }
            }
        }
        return order;
    }
    @Transactional
    public void updateOrder(Order order) {
        orderMapper.update(order);
        // 主動(dòng)失效緩存(旁路刪除)
        redis.delete("order:v2:" + order.getId());
    }
}

? 優(yōu)勢(shì)

  • 緩存 key 語義清晰(含版本 v2,便于灰度/回滾)
  • 支持 TTL、空值緩存、主動(dòng)失效
  • 可集成 緩存命中率監(jiān)控慢查詢告警
  • Flink/Canal 數(shù)據(jù)對(duì)齊 機(jī)制無縫銜接

?? 總結(jié):二級(jí)緩存不是“能不能修”,而是“值不值得用”

方案適合場景高并發(fā)推薦度
MyBatis 原生二級(jí)緩存單機(jī)、低頻、只讀數(shù)據(jù)? 不推薦
mybatis-redis 插件多實(shí)例、讀多寫少、容忍一定延遲?? 謹(jǐn)慎評(píng)估
自定義 Cache 實(shí)現(xiàn)有強(qiáng)緩存治理能力的團(tuán)隊(duì)?? 成本高
業(yè)務(wù)層自建緩存高并發(fā)、強(qiáng)一致性、可觀測性要求高? 強(qiáng)烈推薦

最終口訣更新:

“二級(jí)緩存看似香,架構(gòu)缺陷難躲藏;
分頁排序易沖突,多機(jī)部署更遭殃;
插件替換治標(biāo)難,自建緩存才穩(wěn)當(dāng);
Key 帶版本加 TTL,高并發(fā)下不慌張!”

如果你正在設(shè)計(jì)高并發(fā)系統(tǒng),放棄對(duì) MyBatis 二級(jí)緩存的幻想,把緩存控制權(quán)拿回業(yè)務(wù)層,才是真正的“韌性設(shè)計(jì)”。

到此這篇關(guān)于MyBatis 原生二級(jí)緩存“難以修復(fù)”的原因解析及解決方案的文章就介紹到這了,更多相關(guān)mybatis二級(jí)緩存修復(fù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一篇文章帶你入門Java多線程

    一篇文章帶你入門Java多線程

    這篇文章主要介紹了java多線程編程實(shí)例,分享了幾則多線程的實(shí)例代碼,具有一定參考價(jià)值,加深多線程編程的理解還是很有幫助的,需要的朋友可以參考下
    2021-08-08
  • java實(shí)現(xiàn)樹形菜單對(duì)象

    java實(shí)現(xiàn)樹形菜單對(duì)象

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)樹形菜單對(duì)象,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • img 加載網(wǎng)絡(luò)圖片失敗 顯示默認(rèn)圖片的方法

    img 加載網(wǎng)絡(luò)圖片失敗 顯示默認(rèn)圖片的方法

    下面小編就為大家?guī)硪黄猧mg 加載網(wǎng)絡(luò)圖片失敗 顯示默認(rèn)圖片的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • MyBatis圖文并茂講解注解開發(fā)一對(duì)一查詢

    MyBatis圖文并茂講解注解開發(fā)一對(duì)一查詢

    這篇文章主要介紹了SpringBoot中Mybatis注解一對(duì)一查詢的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Mybatis如何使用動(dòng)態(tài)語句實(shí)現(xiàn)批量刪除(delete結(jié)合foreach)

    Mybatis如何使用動(dòng)態(tài)語句實(shí)現(xiàn)批量刪除(delete結(jié)合foreach)

    這篇文章主要介紹了Mybatis如何使用動(dòng)態(tài)語句實(shí)現(xiàn)批量刪除(delete結(jié)合foreach),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java超詳細(xì)分析抽象類和接口的使用

    Java超詳細(xì)分析抽象類和接口的使用

    在類中沒有包含足夠的信息來描繪一個(gè)具體的對(duì)象,這樣的類稱為抽象類,接口是Java中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java抽象類和接口,感興趣的朋友一起看看吧
    2022-04-04
  • 微信隨機(jī)生成紅包金額算法java版

    微信隨機(jī)生成紅包金額算法java版

    這篇文章主要為大家詳細(xì)介紹了java和php版的微信隨機(jī)生成紅包金額算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Spring?Boot應(yīng)用啟動(dòng)后立即關(guān)閉的原因及解決實(shí)現(xiàn)步驟

    Spring?Boot應(yīng)用啟動(dòng)后立即關(guān)閉的原因及解決實(shí)現(xiàn)步驟

    我們?cè)谛陆⊿pringBoot項(xiàng)目的時(shí)候,有時(shí)在運(yùn)行的時(shí)候,會(huì)遇到一會(huì)就自動(dòng)關(guān)閉了的問題,這篇文章主要介紹了Spring?Boot應(yīng)用啟動(dòng)后立即關(guān)閉的原因及解決實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2025-09-09
  • java唯一字符串ID生成方案詳解

    java唯一字符串ID生成方案詳解

    這篇文章主要給大家介紹了關(guān)于java唯一字符串ID生成方案的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • RocketMQ4.5.X 實(shí)現(xiàn)修改生產(chǎn)者消費(fèi)者日志保存路徑

    RocketMQ4.5.X 實(shí)現(xiàn)修改生產(chǎn)者消費(fèi)者日志保存路徑

    這篇文章主要介紹了RocketMQ4.5.X 實(shí)現(xiàn)修改生產(chǎn)者消費(fèi)者日志保存路徑方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評(píng)論

盐津县| 鹤峰县| 河间市| 五常市| 江陵县| 嘉祥县| 罗源县| 鄢陵县| 正镶白旗| 扶余县| 应用必备| 金阳县| 衡山县| 宝丰县| 顺义区| 东兰县| 三门峡市| 九江县| 农安县| 民丰县| 新津县| 江阴市| 红原县| 齐齐哈尔市| 阿巴嘎旗| 眉山市| 山西省| 马山县| 永年县| 修武县| 察隅县| 余干县| 三河市| 蒲江县| 彭阳县| 平原县| 宜宾市| 嘉峪关市| 中山市| 南木林县| 定州市|