MyBatis緩存機(jī)制深度解析

2025-01-10 11:18 更新

MyBatis 是一個(gè)流行的 Java 持久層框架,它提供了對(duì)數(shù)據(jù)庫的簡單操作和映射。MyBatis 的緩存機(jī)制是其核心特性之一,它可以幫助開發(fā)者提高應(yīng)用程序的性能,通過減少對(duì)數(shù)據(jù)庫的直接訪問次數(shù)來降低數(shù)據(jù)庫的負(fù)載。

1. MyBatis 緩存介紹

默認(rèn)緩存行為

  • 局部的 session 緩存:MyBatis 默認(rèn)開啟的緩存是局部的 session 緩存,這意味著每個(gè) MyBatis session 都會(huì)有自己的緩存,這個(gè)緩存僅在當(dāng)前 session 內(nèi)有效。它主要用于處理循環(huán)依賴和提升性能。

二級(jí)緩存(全局緩存)

  • 開啟二級(jí)緩存:要開啟 MyBatis 的二級(jí)緩存,需要在 SQL 映射文件中添加 <cache/> 標(biāo)簽。這將允許跨多個(gè) session 共享緩存。

緩存的基本屬性

  • select 語句緩存:所有 select 語句的結(jié)果都會(huì)被緩存。
  • 刷新機(jī)制:insert, update 和 delete 語句會(huì)觸發(fā)緩存的刷新。
  • LRU 算法:默認(rèn)使用最近最少使用(Least Recently Used)算法來決定哪些緩存項(xiàng)應(yīng)該被移除。
  • 無時(shí)間刷新:默認(rèn)情況下,緩存不會(huì)根據(jù)時(shí)間間隔自動(dòng)刷新。
  • 引用數(shù)量:默認(rèn)情況下,緩存可以存儲(chǔ) 1024 個(gè)引用。
  • 可讀/可寫:默認(rèn)情況下,緩存是可讀寫的,這意味著緩存的對(duì)象可以被調(diào)用者修改,而不會(huì)干擾其他調(diào)用者或線程。

高級(jí)緩存配置

  • eviction(回收策略):可以設(shè)置不同的回收策略,如 LRU、FIFO、SOFT 和 WEAK。
    • LRU:最近最少使用,移除最長時(shí)間不被使用的對(duì)象。
    • FIFO:先進(jìn)先出,按對(duì)象進(jìn)入緩存的順序移除。
    • SOFT:軟引用,基于垃圾收集器狀態(tài)和軟引用規(guī)則移除對(duì)象。
    • WEAK:弱引用,更積極地移除對(duì)象,基于垃圾收集器狀態(tài)和弱引用規(guī)則。
  • flushInterval(刷新間隔):可以設(shè)置一個(gè)時(shí)間間隔,以毫秒為單位,緩存會(huì)在該時(shí)間間隔后自動(dòng)刷新。
  • size(引用數(shù)目):可以設(shè)置緩存中存儲(chǔ)的對(duì)象或列表的引用數(shù)量,需要根據(jù)可用內(nèi)存資源來決定。
  • readOnly(只讀):設(shè)置為 true 時(shí),所有調(diào)用者將獲得緩存對(duì)象的相同實(shí)例,這些對(duì)象不能被修改,提供了性能優(yōu)勢。設(shè)置為 false 時(shí),緩存對(duì)象可以被修改,但會(huì)返回對(duì)象的拷貝,這會(huì)降低性能。

配置示例

以下是一個(gè)配置示例,展示了如何使用 <cache> 標(biāo)簽來自定義緩存行為:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

  • eviction="FIFO":使用先進(jìn)先出的策略來管理緩存。
  • flushInterval="60000":每 60 秒刷新一次緩存。
  • size="512":緩存可以存儲(chǔ) 512 個(gè)引用。
  • readOnly="true":緩存對(duì)象是只讀的,不能被修改。

2. 四種回收策略的原理分析

1. LRU

LRU(Least Recently Used)算法是一種常見的緩存回收策略,用于決定哪些數(shù)據(jù)應(yīng)該被從緩存中移除以騰出空間給新數(shù)據(jù)。這種策略基于一個(gè)簡單的理念:如果數(shù)據(jù)在一段時(shí)間內(nèi)沒有被使用,那么它在未來被使用的可能性也相對(duì)較低。下面詳細(xì)介紹LRU算法的實(shí)現(xiàn)原理:

數(shù)據(jù)結(jié)構(gòu)

LRU算法通常使用以下兩種數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn):

  1. 哈希表(Hash Map):用于快速定位緩存項(xiàng),O(1)時(shí)間復(fù)雜度。
  2. 雙向鏈表(Doubly Linked List):用于維護(hù)緩存項(xiàng)的使用順序,允許快速添加和刪除節(jié)點(diǎn)。

工作原理

  1. 緩存訪問:當(dāng)緩存被訪問時(shí)(無論是讀取還是寫入),該緩存項(xiàng)會(huì)被視為“最近使用”的,并移動(dòng)到雙向鏈表的頭部(最近使用的位置)。
  2. 緩存添加:當(dāng)新數(shù)據(jù)被添加到緩存時(shí),如果緩存未滿,新數(shù)據(jù)會(huì)被添加到鏈表頭部。如果緩存已滿,則鏈表尾部的數(shù)據(jù)(最不常用的數(shù)據(jù))會(huì)被移除,新數(shù)據(jù)添加到頭部。
  3. 緩存淘汰:當(dāng)緩存達(dá)到容量上限時(shí),鏈表尾部的數(shù)據(jù)(最長時(shí)間未被使用的數(shù)據(jù))會(huì)被移除,為新數(shù)據(jù)騰出空間。

具體實(shí)現(xiàn)步驟

  1. 初始化:創(chuàng)建一個(gè)空的哈希表和一個(gè)空的雙向鏈表。
  2. 訪問緩存
    • 檢查數(shù)據(jù)是否在哈希表中:
      • 如果在,更新該數(shù)據(jù)在鏈表中的位置(移動(dòng)到頭部),并返回?cái)?shù)據(jù)。
      • 如果不在,從數(shù)據(jù)源獲取數(shù)據(jù),添加到鏈表頭部,并在哈希表中創(chuàng)建條目。
  3. 添加數(shù)據(jù)
    • 如果緩存未滿,直接添加數(shù)據(jù)到鏈表頭部,并在哈希表中創(chuàng)建條目。
    • 如果緩存已滿,先從鏈表尾部移除最不常用的數(shù)據(jù),并從哈希表中刪除相應(yīng)條目,然后添加新數(shù)據(jù)到鏈表頭部。
  4. 維護(hù)順序:每次訪問或添加數(shù)據(jù)時(shí),都需要更新數(shù)據(jù)在雙向鏈表中的位置,確保最近使用的數(shù)據(jù)總是在鏈表頭部。

性能考慮

  • 時(shí)間復(fù)雜度:LRU算法在訪問和添加數(shù)據(jù)時(shí)都能保持O(1)的時(shí)間復(fù)雜度,這得益于哈希表和雙向鏈表的結(jié)合使用。
  • 空間復(fù)雜度:主要取決于緩存的大小,即存儲(chǔ)的數(shù)據(jù)量。

應(yīng)用場景

LRU算法廣泛應(yīng)用于操作系統(tǒng)的頁面置換算法、Web服務(wù)器的圖片或資源緩存、數(shù)據(jù)庫查詢結(jié)果緩存等領(lǐng)域,以提高系統(tǒng)性能和響應(yīng)速度。

示例代碼(偽代碼)

class LRUCache {
    HashMap<Integer, Node> map;
    DoublyLinkedList cacheList;
    int capacity;


    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.map = new HashMap<>();
        this.cacheList = new DoublyLinkedList();
    }


    public get(int key) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            cacheList.moveToHead(node); // Move to head to mark as recently used
            return node.value;
        }
        return -1; // Not found
    }


    public put(int key, int value) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            node.value = value;
            cacheList.moveToHead(node);
        } else {
            Node newNode = new Node(key, value);
            map.put(key, newNode);
            cacheList.addHead(newNode);
            if (map.size() > capacity) {
                Node tail = cacheList.removeTail();
                map.remove(tail.key);
            }
        }
    }
}


class Node {
    int key;
    int value;
    Node prev;
    Node next;


    public Node(int key, int value) {
        this.key = key;
        this.value = value;
    }
}


class DoublyLinkedList {
    Node head;
    Node tail;


    public addHead(Node node) {
        // Add node to the head of the list
    }


    public removeTail() {
        // Remove node from the tail of the list and return it
    }


    public moveToHead(Node node) {
        // Move node to the head of the list
    }
}

以上是對(duì)LRU算法實(shí)現(xiàn)原理的詳細(xì)介紹,包括其數(shù)據(jù)結(jié)構(gòu)、工作原理、具體實(shí)現(xiàn)步驟以及性能和應(yīng)用場景。

2. FIFO

FIFO(First In, First Out)算法是一種簡單的緩存回收策略,它按照數(shù)據(jù)進(jìn)入緩存的順序來決定哪些數(shù)據(jù)應(yīng)該被移除。這種策略的核心思想是:最先進(jìn)入緩存的數(shù)據(jù)將會(huì)是最先被移除的數(shù)據(jù)。FIFO算法在實(shí)現(xiàn)上相對(duì)簡單,但可能不如LRU(最近最少使用)算法那樣高效,特別是在某些訪問模式下。以下是FIFO算法的實(shí)現(xiàn)原理和詳細(xì)步驟:

數(shù)據(jù)結(jié)構(gòu)

FIFO算法通常使用以下數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn):

  1. 隊(duì)列(Queue):用于維護(hù)緩存項(xiàng)的順序,確保最先進(jìn)入的數(shù)據(jù)最先被移除。
  2. 哈希表(Hash Map):用于快速定位緩存項(xiàng),提供O(1)時(shí)間復(fù)雜度的訪問。

工作原理

  1. 緩存訪問:當(dāng)緩存被訪問時(shí)(無論是讀取還是寫入),該緩存項(xiàng)會(huì)被視為“最近使用”的。
  2. 緩存添加
    • 如果緩存未滿,新數(shù)據(jù)會(huì)被添加到隊(duì)列的尾部。
    • 如果緩存已滿,隊(duì)列頭部的數(shù)據(jù)會(huì)被移除,新數(shù)據(jù)添加到隊(duì)列尾部。
  3. 緩存淘汰:當(dāng)緩存達(dá)到容量上限時(shí),隊(duì)列頭部的數(shù)據(jù)(最先進(jìn)入的數(shù)據(jù))會(huì)被移除,為新數(shù)據(jù)騰出空間。

具體實(shí)現(xiàn)步驟

  1. 初始化:創(chuàng)建一個(gè)空的隊(duì)列和一個(gè)空的哈希表。
  2. 訪問緩存
    • 檢查數(shù)據(jù)是否在哈希表中:
      • 如果在,返回?cái)?shù)據(jù),但不需要移動(dòng)數(shù)據(jù)在隊(duì)列中的位置。
      • 如果不在,從數(shù)據(jù)源獲取數(shù)據(jù),添加到隊(duì)列尾部,并在哈希表中創(chuàng)建條目。
  3. 添加數(shù)據(jù)
    • 如果緩存未滿,直接添加數(shù)據(jù)到隊(duì)列尾部,并在哈希表中創(chuàng)建條目。
    • 如果緩存已滿,先從隊(duì)列頭部移除最舊的數(shù)據(jù),并從哈希表中刪除相應(yīng)條目,然后添加新數(shù)據(jù)到隊(duì)列尾部。
  4. 維護(hù)順序:每次添加新數(shù)據(jù)時(shí),都需要更新隊(duì)列和哈希表。

性能考慮

  • 時(shí)間復(fù)雜度:FIFO算法在訪問和添加數(shù)據(jù)時(shí)都能保持O(1)的時(shí)間復(fù)雜度,這得益于哈希表的使用。
  • 空間復(fù)雜度:主要取決于緩存的大小,即存儲(chǔ)的數(shù)據(jù)量。

應(yīng)用場景

FIFO算法由于其簡單性,適用于那些對(duì)緩存一致性要求不高的場景。它可能不適用于那些頻繁訪問某些數(shù)據(jù)的應(yīng)用程序,因?yàn)檫@些數(shù)據(jù)可能會(huì)被錯(cuò)誤地移除。

示例代碼(偽代碼)

class FIFOCache {
    HashMap<Integer, Integer> map;
    LinkedList<Integer> queue;
    int capacity;


    public FIFOCache(int capacity) {
        this.capacity = capacity;
        this.map = new HashMap<>();
        this.queue = new LinkedList<>();
    }


    public get(int key) {
        if (map.containsKey(key)) {
            return map.get(key);
        }
        return -1; // Not found
    }


    public put(int key, int value) {
        if (map.containsKey(key)) {
            // Key already exists, update the value and remove the key from the queue
            queue.remove(map.get(key));
            map.put(key, value);
            queue.addLast(key);
        } else {
            if (map.size() >= capacity) {
                // Cache is full, remove the oldest item
                int oldestKey = queue.removeFirst();
                map.remove(oldestKey);
            }
            // Add new item
            map.put(key, value);
            queue.addLast(key);
        }
    }
}


class LinkedList {
    Node head;
    Node tail;


    public addLast(int value) {
        // Add value to the end of the list
    }


    public removeFirst() {
        // Remove the first element from the list and return it
    }
}


class Node {
    int value;
    Node next;


    public Node(int value) {
        this.value = value;
    }
}

以上是對(duì)FIFO算法實(shí)現(xiàn)原理的詳細(xì)介紹,包括其數(shù)據(jù)結(jié)構(gòu)、工作原理、具體實(shí)現(xiàn)步驟以及性能和應(yīng)用場景。FIFO算法雖然簡單,但在某些情況下可能不如LRU算法有效,特別是在數(shù)據(jù)訪問模式不均勻的情況下。

3. SOFT

SOFT(軟引用)是一種緩存回收策略,它在 Java 中通過 java.lang.ref.SoftReference 類實(shí)現(xiàn)。軟引用允許對(duì)象在內(nèi)存不足時(shí)被垃圾收集器回收,但只要內(nèi)存足夠,這些對(duì)象就可以繼續(xù)存活。這種策略特別適用于緩存機(jī)制,因?yàn)樗梢栽诓挥绊憫?yīng)用程序功能的情況下,動(dòng)態(tài)地釋放內(nèi)存資源。以下是 SOFT 緩存策略的實(shí)現(xiàn)原理和詳細(xì)步驟:

工作原理

  1. 軟引用:軟引用是一種比強(qiáng)引用(Strong Reference)弱,但比弱引用(Weak Reference)強(qiáng)的引用類型。軟引用關(guān)聯(lián)的對(duì)象在內(nèi)存不足時(shí)可以被垃圾收集器回收,但只要內(nèi)存足夠,它們就會(huì)繼續(xù)存活。
  2. 垃圾收集器:Java 的垃圾收集器會(huì)定期檢查內(nèi)存使用情況,并在內(nèi)存不足時(shí)嘗試回收軟引用對(duì)象。
  3. 緩存管理:使用軟引用實(shí)現(xiàn)的緩存會(huì)在內(nèi)存不足時(shí)自動(dòng)釋放緩存對(duì)象,從而為新對(duì)象騰出空間。

具體實(shí)現(xiàn)步驟

  1. 初始化緩存:創(chuàng)建一個(gè)緩存容器,如 HashMap,用于存儲(chǔ)鍵和軟引用對(duì)象的映射。
  2. 訪問緩存
    • 當(dāng)訪問緩存時(shí),首先檢查軟引用是否仍然有效(即其關(guān)聯(lián)的對(duì)象是否已被回收)。
    • 如果軟引用有效,返回其關(guān)聯(lián)的對(duì)象。
    • 如果軟引用無效,說明對(duì)象已被回收,可以重新從數(shù)據(jù)源獲取數(shù)據(jù),并創(chuàng)建新的軟引用。
  3. 添加數(shù)據(jù)
    • 當(dāng)添加新數(shù)據(jù)到緩存時(shí),使用 SoftReference 包裝該對(duì)象,并將其存儲(chǔ)在緩存容器中。
    • 由于軟引用的特性,如果內(nèi)存不足,這些對(duì)象可能會(huì)被垃圾收集器回收。
  4. 內(nèi)存回收:當(dāng)系統(tǒng)內(nèi)存不足時(shí),垃圾收集器會(huì)嘗試回收軟引用對(duì)象。這使得緩存可以自動(dòng)調(diào)整大小,釋放不再需要的內(nèi)存。

性能考慮

  • 時(shí)間復(fù)雜度:訪問和添加數(shù)據(jù)的時(shí)間復(fù)雜度通常為 O(1),因?yàn)?HashMap 提供了快速的鍵值對(duì)查找。
  • 空間復(fù)雜度:緩存的大小取決于緩存對(duì)象的數(shù)量和每個(gè)對(duì)象的大小,但軟引用允許在內(nèi)存不足時(shí)自動(dòng)回收對(duì)象,從而動(dòng)態(tài)調(diào)整緩存大小。

應(yīng)用場景

軟引用緩存適用于以下場景:

  • 內(nèi)存敏感的應(yīng)用程序:在內(nèi)存資源有限的設(shè)備上,如移動(dòng)設(shè)備或嵌入式系統(tǒng),軟引用緩存可以動(dòng)態(tài)地釋放內(nèi)存。
  • 大對(duì)象緩存:對(duì)于占用大量內(nèi)存的對(duì)象,如圖片或大型文檔,軟引用緩存可以在內(nèi)存不足時(shí)自動(dòng)釋放這些對(duì)象。
  • 可有可無的緩存:在某些情況下,緩存數(shù)據(jù)的丟失不會(huì)對(duì)應(yīng)用程序的功能產(chǎn)生重大影響,軟引用緩存是一個(gè)很好的選擇。

示例代碼(Java)

import java.lang.ref.SoftReference;
import java.util.HashMap;


public class SoftReferenceCache<K, V> {
    private HashMap<K, SoftReference<V>> cache = new HashMap<>();


    public V get(K key) {
        SoftReference<V> ref = cache.get(key);
        if (ref != null) {
            V value = ref.get();
            if (value != null) {
                return value;
            }
            // SoftReference has been cleared, remove it from the cache
            cache.remove(key);
        }
        return null;
    }


    public void put(K key, V value) {
        cache.put(key, new SoftReference<>(value));
    }
}

在這個(gè)示例中,SoftReferenceCache 使用 HashMap 存儲(chǔ)鍵和軟引用對(duì)象的映射。當(dāng)訪問緩存時(shí),首先檢查軟引用是否有效。如果軟引用無效,說明對(duì)象已被回收,可以重新從數(shù)據(jù)源獲取數(shù)據(jù),并創(chuàng)建新的軟引用。

小結(jié)

SOFT 緩存策略通過使用軟引用來實(shí)現(xiàn)緩存對(duì)象的自動(dòng)回收,從而在內(nèi)存不足時(shí)動(dòng)態(tài)地釋放內(nèi)存資源。這種策略特別適用于內(nèi)存敏感的應(yīng)用程序,或者那些緩存數(shù)據(jù)丟失不會(huì)對(duì)應(yīng)用程序功能產(chǎn)生重大影響的場景。

4. WEAK

WEAK(弱引用)是一種比軟引用(Soft Reference)更弱的引用類型,它允許對(duì)象在下一次垃圾收集時(shí)被回收,無論內(nèi)存是否足夠。在 Java 中,弱引用是通過 java.lang.ref.WeakReference 類實(shí)現(xiàn)的。弱引用通常用于實(shí)現(xiàn)緩存,其中對(duì)象的生命周期不需要超過引用本身的生命周期。以下是 WEAK 緩存策略的實(shí)現(xiàn)原理和詳細(xì)步驟:

工作原理

  1. 弱引用:弱引用是一種對(duì)對(duì)象的引用,它不會(huì)阻止垃圾收集器回收其引用的對(duì)象。這意味著只要沒有其他的強(qiáng)引用指向該對(duì)象,對(duì)象就可以被垃圾收集器回收。
  2. 垃圾收集器:Java 的垃圾收集器會(huì)定期執(zhí)行,當(dāng)它發(fā)現(xiàn)某個(gè)對(duì)象只被弱引用所引用時(shí),就會(huì)回收該對(duì)象占用的內(nèi)存。
  3. 緩存管理:使用弱引用實(shí)現(xiàn)的緩存允許對(duì)象在不再被使用時(shí)被快速回收,即使內(nèi)存尚未不足。

具體實(shí)現(xiàn)步驟

  1. 初始化緩存:創(chuàng)建一個(gè)緩存容器,如 HashMap,用于存儲(chǔ)鍵和弱引用對(duì)象的映射。
  2. 訪問緩存
    • 當(dāng)訪問緩存時(shí),首先檢查弱引用是否仍然有效(即其關(guān)聯(lián)的對(duì)象是否已被回收)。
    • 如果弱引用有效,返回其關(guān)聯(lián)的對(duì)象。
    • 如果弱引用無效,說明對(duì)象已被回收,可以重新從數(shù)據(jù)源獲取數(shù)據(jù),并創(chuàng)建新的弱引用。
  3. 添加數(shù)據(jù)
    • 當(dāng)添加新數(shù)據(jù)到緩存時(shí),使用 WeakReference 包裝該對(duì)象,并將其存儲(chǔ)在緩存容器中。
    • 由于弱引用的特性,這些對(duì)象可能會(huì)在下一次垃圾收集時(shí)被回收。
  4. 內(nèi)存回收:當(dāng)垃圾收集器執(zhí)行時(shí),它會(huì)檢查所有弱引用,并回收那些只被弱引用的對(duì)象。

性能考慮

  • 時(shí)間復(fù)雜度:訪問和添加數(shù)據(jù)的時(shí)間復(fù)雜度通常為 O(1),因?yàn)?HashMap 提供了快速的鍵值對(duì)查找。
  • 空間復(fù)雜度:緩存的大小取決于緩存對(duì)象的數(shù)量和每個(gè)對(duì)象的大小,但由于弱引用允許對(duì)象在下一次垃圾收集時(shí)被回收,因此緩存不會(huì)長時(shí)間占用大量內(nèi)存。

應(yīng)用場景

弱引用緩存適用于以下場景:

  • 內(nèi)存敏感的應(yīng)用程序:在內(nèi)存資源有限的設(shè)備上,如移動(dòng)設(shè)備或嵌入式系統(tǒng),弱引用緩存可以快速釋放內(nèi)存。
  • 臨時(shí)對(duì)象緩存:對(duì)于只在特定時(shí)間內(nèi)需要的對(duì)象,使用弱引用緩存可以確保這些對(duì)象在不再需要時(shí)迅速被回收。
  • 可丟棄的緩存:在某些情況下,緩存數(shù)據(jù)的丟失不會(huì)對(duì)應(yīng)用程序的功能產(chǎn)生重大影響,弱引用緩存是一個(gè)很好的選擇。

示例代碼(Java)

import java.lang.ref.WeakReference;
import java.util.HashMap;


public class WeakReferenceCache<K, V> {
    private HashMap<K, WeakReference<V>> cache = new HashMap<>();


    public V get(K key) {
        WeakReference<V> ref = cache.get(key);
        if (ref != null) {
            V value = ref.get();
            if (value != null) {
                return value;
            }
            // WeakReference has been cleared, remove it from the cache
            cache.remove(key);
        }
        return null;
    }


    public void put(K key, V value) {
        cache.put(key, new WeakReference<>(value));
    }
}

在這個(gè)示例中,WeakReferenceCache 使用 HashMap 存儲(chǔ)鍵和弱引用對(duì)象的映射。當(dāng)訪問緩存時(shí),首先檢查弱引用是否有效。如果弱引用無效,說明對(duì)象已被回收,可以重新從數(shù)據(jù)源獲取數(shù)據(jù),并創(chuàng)建新的弱引用。

小結(jié)

WEAK 緩存策略通過使用弱引用來實(shí)現(xiàn)緩存對(duì)象的快速回收,這對(duì)于內(nèi)存敏感的應(yīng)用程序或臨時(shí)對(duì)象的緩存非常有用。這種策略允許應(yīng)用程序在不犧牲內(nèi)存的情況下,臨時(shí)存儲(chǔ)和管理數(shù)據(jù)對(duì)象。

最后

MyBatis 的緩存機(jī)制非常靈活,可以通過簡單的配置來滿足不同的性能需求。合理地使用緩存可以顯著提高應(yīng)用程序的性能,尤其是在處理大量數(shù)據(jù)庫查詢時(shí)。然而,開發(fā)者需要注意緩存的一致性和并發(fā)問題,特別是在使用可讀寫緩存時(shí)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)