redis 的過期策略都有哪些?記憶體淘汰機制都有哪些?手寫一下 LRU 代碼實現?

来源:https://www.cnblogs.com/midoujava/archive/2019/09/18/11545933.html
-Advertisement-
Play Games

面試題 redis 的過期策略都有哪些?記憶體淘汰機制都有哪些?手寫一下 LRU 代碼實現? 面試官心理分析 如果你連這個問題都不知道,上來就懵了,回答不出來,那線上你寫代碼的時候,想當然的認為寫進 redis 的數據就一定會存在,後面導致系統各種 bug,誰來負責? 常見的有兩個問題: 往 redi ...


關註米兜Java.md

面試題

redis 的過期策略都有哪些?記憶體淘汰機制都有哪些?手寫一下 LRU 代碼實現?

面試官心理分析

如果你連這個問題都不知道,上來就懵了,回答不出來,那線上你寫代碼的時候,想當然的認為寫進 redis 的數據就一定會存在,後面導致系統各種 bug,誰來負責?

常見的有兩個問題:

  • 往 redis 寫入的數據怎麼沒了?

可能有同學會遇到,在生產環境的 redis 經常會丟掉一些數據,寫進去了,過一會兒可能就沒了。我的天,同學,你問這個問題就說明 redis 你就沒用對啊。redis 是緩存,你給當存儲了是吧?

啥叫緩存?用記憶體當緩存。記憶體是無限的嗎,記憶體是很寶貴而且是有限的,磁碟是廉價而且是大量的。可能一臺機器就幾十個 G 的記憶體,但是可以有幾個 T 的硬碟空間。redis 主要是基於記憶體來進行高性能、高併發的讀寫操作的。

那既然記憶體是有限的,比如 redis 就只能用 10G,你要是往裡面寫了 20G 的數據,會咋辦?當然會幹掉 10G 的數據,然後就保留 10G 的數據了。那幹掉哪些數據?保留哪些數據?當然是幹掉不常用的數據,保留常用的數據了。

  • 數據明明過期了,怎麼還占用著記憶體?

這是由 redis 的過期策略來決定。

面試題剖析

redis 過期策略

redis 過期策略是:定期刪除+惰性刪除

所謂定期刪除,指的是 redis 預設是每隔 100ms 就隨機抽取一些設置了過期時間的 key,檢查其是否過期,如果過期就刪除。

假設 redis 里放了 10w 個 key,都設置了過期時間,你每隔幾百毫秒,就檢查 10w 個 key,那 redis 基本上就死了,cpu 負載會很高的,消耗在你的檢查過期 key 上了。註意,這裡可不是每隔 100ms 就遍歷所有的設置過期時間的 key,那樣就是一場性能上的災難。實際上 redis 是每隔 100ms 隨機抽取一些 key 來檢查和刪除的。

但是問題是,定期刪除可能會導致很多過期 key 到了時間並沒有被刪除掉,那咋整呢?所以就是惰性刪除了。這就是說,在你獲取某個 key 的時候,redis 會檢查一下 ,這個 key 如果設置了過期時間那麼是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。

獲取 key 的時候,如果此時 key 已經過期,就刪除,不會返回任何東西。

但是實際上這還是有問題的,如果定期刪除漏掉了很多過期 key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期 key 堆積在記憶體里,導致 redis 記憶體塊耗盡了,咋整?

答案是:走記憶體淘汰機制

記憶體淘汰機制

redis 記憶體淘汰機制有以下幾個:

  • noeviction: 當記憶體不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太噁心了。
  • allkeys-lru:當記憶體不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)。
  • allkeys-random:當記憶體不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key,這個一般沒人用吧,為啥要隨機,肯定是把最近最少使用的 key 給幹掉啊。
  • volatile-lru:當記憶體不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 key(這個一般不太合適)。
  • volatile-random:當記憶體不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 key。
  • volatile-ttl:當記憶體不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 key 優先移除。

手寫一個 LRU 演算法

你可以現場手寫最原始的 LRU 演算法,那個代碼量太大了,似乎不太現實。

不求自己純手工從底層開始打造出自己的 LRU,但是起碼要知道如何利用已有的 JDK 數據結構實現一個 Java 版的 LRU。

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;

    /**
     * 傳遞進來最多能緩存多少數據
     *
     * @param cacheSize 緩存大小
     */
    public LRUCache(int cacheSize) {
        // true 表示讓 linkedHashMap 按照訪問順序來進行排序,最近訪問的放在頭部,最老訪問的放在尾部。
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 當 map中的數據量大於指定的緩存個數的時候,就自動刪除最老的數據。
        return size() > CACHE_SIZE;
    }
}

本文在米兜公眾號鏈接:
https://mp.weixin.qq.com/s/h3XyW1WgPY9fcMmSMb6pHw

歡迎關註米兜Java,一個註在共用、交流的Java學習平臺。

file


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、電腦結構 五大部件:輸入設備、輸出設備、存儲器、運算器、控制器 二、cpu、硬碟、記憶體三者之間的關係 cpu:是電腦運算核心和控制中心,讓電腦的各個部件順利工作,起到協調和控製作用 硬碟:存儲資料和軟體等數據設備,有容量大,斷電數據不丟失的特點,也被人們稱之為“數據倉庫” 記憶體:a、負責硬碟 ...
  • [TOC] 1. 函數重載回顧 函數重載的本質為相互獨立的不同函數 C++通過函數名和函數參數確定函數調用 無法直接通過函數名得到重載函數的入口地址 函數重載必然發生在同一個作用域中 2. 類中的函數重載 類的成員函數可以進行重載,包括 構造函數的重載 普通成員函數的重載 靜態成員函數的重載 註意: ...
  • [TOC] 1. 靜態成員變數 先來回顧一下普通成員變數 通過對象名能夠訪問public成員變數 每個對象的普通成員變數都是專屬的,不能在對象之間共用 在C++中還可以定義靜態成員變數 靜態成員變數屬於整個類所有,所有對象共用類的靜態成員變數 靜態成員變數的生命周期不依賴於任何對象 可以通過類名和對 ...
  • [TOC] 1. 析構函數 C++的類中可以定義一個特殊的清理函數,叫做析構函數,語法規則為 析構函數沒有參數,也沒有返回值類型聲明 析構函數在對象銷毀時自動被調用 當類中自定義了構造函數,並且構造函數中使用了系統資源(如:堆空間、文件打開,等),則需要自定義析構函數 2. 對象的構造與析構順序 多 ...
  • 在實際的開發中,我們會遇到許多重覆頁面的部分,這些頁面的重覆會讓我們的代碼看起來非常冗餘 所以我們要進行頁面的佈局規劃。思路:將頁面中的公有部分取出來作為單獨的頁面,其他繼承公共模板 在公共模板的基礎上替換占位符內容從而構成新的內容頁面。 @頁面占位符yield和頁面繼承extends 1.使用占位 ...
  • centos7上安裝zookeeper 1 準備工作 1、準備伺服器,本次安裝採用 centos7系統、記憶體2G、存儲60G的虛擬機伺服器一臺; 2、伺服器安裝java環境: 參考文章《centos7上安裝jdk8》博文; 3、準備zookeeper安裝包, 本次採用 zookeeper 3.4.1 ...
  • 前面已經學習了服務註冊與發現組件,負載均衡組件,這樣我們的微服務系統已經可以使用了。為了保證其高可用,單個服務通常會集群部署。由於網路原因或者自身的原因,服務並不能保證 100% 可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,Servlet 容器的線程資源會被消耗 ...
  • 1. 安裝 Namesrv 拉取鏡像 docker pull rocketmqinc/rocketmq:4.4.0` docker run d p 9876:9876 v {RmHome}/data/namesrv/logs:/root/logs v {RmHome}/data/namesrv/st ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...