redis持久化機制與過期策略


RDB的持久化策略

(快照方式,默認持久化方式): 按照規則定時將內存中的數據同步到磁盤,它有以下4個觸發場景。

  1. 自己配置的快照規則  vim /redis/bin/ redis.conf;按照save <seconds> <changes>這個規則自己添加或修改規則。

    

  2. save或者bgsave命令

    save:將內存的數據同步到磁盤中,這個操作會阻塞客戶端的請求(不建議用,太耗時了)。

      bgsave:在后台異步執行快照操作,這個操作不會阻塞客戶端的請求。

  3. 執行flushall清除內存的所有數據時,只要save <seconds> <changes>規則不為空,就會執行快照。

  4. 執行復制的時候(集群中 )

  快照的實現原理與優缺點:

    redis使用fork函數復制出一份當前進程的副本(子進程);父進程繼續處理客戶端指令,子進程開始將內存的數據寫入硬盤中的臨時文件,寫入完成后就會替換之前的舊文件。優點:1. 多進程處理,性能最快。缺點:1. 若子進程數據未寫完而redis異常退出,就會丟失最后一次快照以后更改的所有數據; 2. 如果數據集比較大的時候,fork可以能比較耗時,造成服務器在一段時間內停止處理客戶端的請求。

AOF的持久化策略

  開啟AOF持久化vim /redis/bin/ redis.conf  將appendonly默認值no改為yes; 重啟后執行對數據的變更命令, 會在bin目錄下生成對應的.aof文件, aof文件中會記錄所有的操作命令!

    

  AOF優化:

     auto-aof-rewrite-percentage 100  表示當前aof文件大小超過上一次aof文件大小的百分之多少的時候會進行重寫。如果之前沒有重寫過,以啟動時aof文件大小為准

     auto-aof-rewrite-min-size 64mb   限制允許重寫最小aof文件大小,也就是文件大小小於64mb的時候,不需要進行重寫。

    

   aof重寫原理:

    執行redis命令的時候,會把命令寫入到.aof文件中,.aof文件變得過大時后台會對它進行重寫。在將命令寫入到.aof時,即使重寫過程發生了停機,現有的.aof文件也不會丟失,所以它是絕對安全的。

   同步磁盤數據:

    redis在變更數據時,命令會實時記錄到.aof文件。但是由於操作系統的緩存機制,數據不是直接寫入到硬盤,而是寫入硬盤緩存,再通過硬盤緩存機制刷新保存到文件。

      appendfsync always  每次執行寫入都會進行同步  , 這個是最安全但是是效率比較低的方式

      appendfsync everysec   每一秒執行

      appendfsync no  不主動進行同步操作,由操作系統去執行,這個是最快但是最不安全的方式

      

  2.4 aof文件損壞以后如何修復:

    例如在執行set name wulei時候,文件只記錄了set name  ,這種不完整的命令是無法被寫入磁盤的。我們可以先將.aof文件備份,然后通過redis-check-aof --fix命令修復,它會將一些不合法的命令清理掉,這樣就能被持久化了。

  如果要保證數據絕對安全: 可以使用  RDB+AOF 方式來持久化。如果同時使用的話, 那么Redis重啟時,會優先使用AOF文件來還原數據。

  如果可以接受幾分鍾的數據丟失:可以使用RDB方式,因為AOF速度沒有RDB快。

============================  手動分割線  ==============================

Redis的過期策略

  redis過期是(定期刪除+惰性刪除+內存淘汰機制)來實現的。reids是用內存來緩存的,內存資源很寶貴。所以我們 set key value 的時候一般都會給它設置過期時間。假設redis里放了10萬個數據,redis默認會每隔100ms隨機抽取設置了過期時間的key來刪除(如果一次性檢查所有數據,cpu負載過高redis早就死了),這種方式就叫定期刪除。這種策略就會導致很多過期的key並沒有被刪除,所以還有惰性刪除, 也就是在你獲取某個key的時候,redis會檢查一下,這個key是否過期了,如果是就直接刪除不返回任何東西!

  但是這種方式還是有問題的,比如10萬條全過期了,而redis只定期刪除了部分,而客戶端有沒有對剩下的key操作,key就不會被刪除,還是會造成內存的積壓。這時候就會走內存淘汰機制,例如:

    allkeys-lru:當內存不足以容納新寫入數據時,移除最近最少使用的key。(最常用)

    volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵中,將更早過期時間的key優先移除。(還湊合吧)

    noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。(腦殘的策略,沒人用)

    allkeys-random:當內存不足以容納新寫入數據時,隨機移除某個key。(腦殘的策略,沒人用)

    volatile-lru:當內存不足以容納新寫入數據時,在設了過期時間的鍵中,移除最近最少使用的key。(腦殘的策略,沒人用)

    volatile-random:當內存不足以容納新寫入數據時,在設了過期時間的鍵中,隨機移除某個key。(腦殘的策略,沒人用)

緩存淘汰算法LFU算法

  lfu算法是根據數據的歷史訪問頻率來淘汰數據的,其核心思想是"如果數據過去被訪問多次,那么將來被訪問的頻率也更高".
  缺點:
  1. 有存儲成本,需要維護隊列的引用計數,2.最后添加的數據容易被移除
LFU算法原理剖析
  1. 新加入的數據插入到隊列尾部(因為引用計數為1)
  2. 隊列中的數據被訪問后,其引用計數增加,隊列重新排序
  3. 當需要淘汰數據時,將已經排序的列表最后的數據塊刪除

  

緩存淘汰算法LRU算法

  根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是“如果數據最近被訪問過,那么將來被訪問的幾率也更高”
LRU算法原理剖析
  1. lru按照一定順序維護着隊列
  2. 隊列中的數據被訪問后,數據會被排列到最前面
  3. 當需要淘汰數據時,將已經排序的列表最后的數據塊刪除
  

手寫LRU算法

import java.util.LinkedHashMap;
import java.util.Map;

// lru是有序的,所以這里繼承 LinkedHashMap
public class LRUCache<K,V> extends LinkedHashMap<K,V> {

    private final int CACHE_SIZE;
    /**
     * 傳遞進來最多能緩存多少數據
     *
     * @param cacheSize 緩存大小
     */
    public LRUCache(int cacheSize) {
        /*
            cacheSize是map的初始大小
            0.75f是加載因子,容量使用率達到0.75就會擴容一倍
            true 表示讓 linkedHashMap 按照訪問順序來進行排序,最近訪問的放在頭部,最老訪問的放在尾部。
         */
        super(cacheSize, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 當前map中的數據量大於指定的緩存個數的時候,就自動刪除最老的數據。
        boolean b = size() > CACHE_SIZE;
        if(b){
            System.out.println("清除緩存key:"+eldest.getKey());
        }
        return b;
    }
    public static void main(String args[]){
        LRUCache<String, String> lruCache = new LRUCache<String, String>(3);
        lruCache.put("1", "1");
        lruCache.put("2", "2");
        lruCache.put("3", "3");
        lruCache.put("4", "4");
        System.out.println("初始化完成:"+lruCache.keySet());
        System.out.println(lruCache.get("3"));
        System.out.println("訪問3之后:"+lruCache.keySet());
        System.out.println(lruCache.get("2"));
        System.out.println("訪問2之后:"+lruCache.keySet());
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM