【Redis】-- 核心原理

一、簡介

分佈式緩存是分佈式系統中的重要組件,主要解決高併發、大數據場景下,熱點數據訪問的性能問題,提供高性能的數據快速訪問。
使用緩存常見場景是:項目中部分數據訪問比較頻繁,對下游 DB(例如 MySQL)造成服務壓力,這時候可以使用緩存來提高效率。
緩存組件有很多種,大家熟知的 Redis、Tair、MemCache 等。今天我們重點介紹 Redis 緩存數據庫相關的內容知識。
Redis 是開源免費,性能不錯的 key-value 數據庫。Redis 的特點包括:

  1. Redis 除了支持 key-value 類型的數據,同時還支持其他多種數據結構的存儲;
  2. Redis 支持數據持久化存儲,可以將數據存儲在磁盤中,機器重啓數據將從磁盤重新加載數據;
  3. Redis 支持數據的備份,即 Master-Slave 模式的數據備份。

Redis 作爲緩存數據庫和 MySQL 這種結構化數據庫進行對比。

  1. **從數據庫類型上,**Redis 是 NoSQL 半結構化緩存數據庫, MySQL 是結構化關係型數據庫;
  2. **從讀寫性能上,**MySQL 是持久化硬盤存儲,讀寫速度較慢, Redis 數據存儲讀取都在內存,同時也可以持久化到磁盤,讀寫速度較快;
  3. **從使用場景上,**Redis 一般作爲 MySQL 數據讀取性能優化的技術選型,彼此配合使用。

接下來我們將重點向大家介紹關於 Redis 幾個方向的知識內容:

  1. Redis 基本數據結構與實戰場景
  2. Redis 常見異常及解決方案
  3. 分佈式環境下常見的應用場景
  4. Redis 集羣模式的介紹與總結
  5. Redis 常見面試題目詳解

二、Redis 基本數據結構與實戰場景

2.1 基本類型

我們用一個簡單的導圖來簡單複習一下 Redis 的基本數據類型:

2.2 常用指令

接下來看看每個數據結構常用的指令有哪些,我們用一張表比較清晰的展示:

序號 數據結構 常用命令 命令實例
1 String 1.set :設置 key 對應的 value 值
2.get : 獲取對應 key 的值,如不存在返回 nil
3.setnx : 只有設置的值不存在,才設置
4.setex :設置鍵值,並指定對應的有效期
5.mset/mget : 一次設置/獲取多個 key 的值
6.incr/decr : 對 key 值進行增加 / 減去 1 操作
1.set name “tom”
2.get name 結果 :tom
3.setnx name “jim”
4.setex name 10 “tom”
5.mset key1 “hh” key2 “kk”
6.+1/-1
2 list 1.lpush/rpush :在 key 所對應的 list 左 / 右部添加一個元素
2.lrang/lindex :獲取列表給定範圍 / 位置的所有值
3.lset :設置 list 中指定下表元素的值
1.lpush list_name value1; rpush list_name value2
2.lrang list_name 0 -1 獲取列表所有元素
3.lset list_name 1 valuex
3 set 1.sadd :向名稱 爲key 的 set 添加元素
2.smembers :查看集合中的所有成員
3.spop :隨機返回並刪除 set 中一個元素
4.sdiff :返回所有 set 與第一個 set 的差集
5.sunion :返回給定集合並集
1.sadd wordset aa; sadd wordiest bb;
2.smembers wordset
3.spop wordset
4.sdiff wordset wordset1
5.sunion wordset wordset1
4 hash 1.hset :設置一個 hash 的 field 的指定值,如果 key 不存在先創建
2.hget :獲取某個 hash 的某個 filed 值
3.hmset/hmget :批量設置 / 獲取 hash 內容
4.hlen :返回 hash 表中 key 的數量
5.hkeys/hvals :返回 hash 表中所有的 key/value
1.hset user name “tom"
2.hget user name
3.hmget user name sex
4.hlen user
5.hkeys user / hvals user
5 Sorted set 1.zadd :將一個帶有給定分值的成員添加到有序集合裏面
2.zrange :取出集合中的元素
3.zcard :返回集合中所有元素的個數
1.zadd key 1 hello
2.zrang key 0 -1
3.zcard key

2.3 場景解析

2.3.1 String 類型使用場景

場景一:商品庫存數
從業務上,商品庫存數據是熱點數據,交易行爲會直接影響庫存。而 Redis 自身 String 類型提供了:

incr key   && decr key   &&  incrby key increment  &&  decrby key decrement
  1. set goods_id 10; 設置 id 爲 good_id 的商品的庫存初始值爲 10;
  2. decr goods_id; 當商品被購買時候,庫存數據減 1。

依次類推的場景:商品的瀏覽次數,問題或者回復的點贊次數等。這種計數的場景都可以考慮利用 Redis 來實現。
場景二:時效信息存儲
Redis 的數據存儲具有自動失效能力。也就是存儲的 key-value 可以設置過期時間:set(key, value, expireTime)
比如,用戶登錄某個 App 需要獲取登錄驗證碼, 驗證碼在 30 秒內有效。那麼我們就可以使用 String 類型存儲驗證碼,同時設置 30 秒的失效時間。

keys = redisCli.get(key);
     if(keys != null)
    {
        return false;
    }
    else
    {
        sendMsg()
        redisCli.set(keys,value,expireTime)
    }

2.3.2 List 類型使用場景

list 是按照插入順序排序的字符串鏈表。可以在頭部和尾部插入新的元素(雙向鏈表實現,兩端添加元素的時間複雜度爲 O(1)) 。
場景一:消息隊列實現
目前有很多專業的消息隊列組件 Kafka、RabbitMQ 等。 我們在這裏僅僅是使用 list 的特徵來實現消息隊列的要求。在實際技術選型的過程中,大家可以慎重思考。
list 存儲就是一個隊列的存儲形式:

  1. lpush key value; 在 key 對應 list 的頭部添加字符串元素;
  2. rpop key;移除列表的最後一個元素,返回值爲移除的元素。

場景二:最新上架商品
在交易網站首頁經常會有新上架產品推薦的模塊, 這個模塊是存儲了最新上架前 100 名。
這時候使用 Redis 的 list 數據結構,來進行 TOP 100 新上架產品的存儲。
Redis ltrim 指令對一個列表進行修剪(trim),這樣 list 就會只包含指定範圍的指定元素。

ltrim key start stop

start 和 stop 都是由 0 開始計數的,這裏的 0 是列表裏的第一個元素(表頭),1 是第二個元素。
如下僞代碼演示:

//把新上架商品添加到鏈表裏
    ret = r.lpush(“new:goods", goodsId)
    //保持鏈表 100 位
    ret = r.ltrim("new:goods", 0, 99)
    //獲得前 100 個最新上架的商品 id 列表
    newest_goods_list = r.lrange("new:goods", 0, 99)

2.3.3 set 類型使用場景

set 也是存儲了一個集合列表功能。和 list 不同,set 具備去重功能。當需要存儲一個列表信息,同時要求列表內的元素不能有重複,這時候使用 set 比較合適。與此同時,set 還提供的交集、並集、差集。
例如,在交易網站,我們會存儲用戶感興趣的商品信息,在進行相似用戶分析的時候, 可以通過計算兩個不同用戶之間感興趣商品的數量來提供一些依據。

//userid 爲用戶 ID , goodID 爲感興趣的商品信息。 
    sadd “user:userId” goodID; 
    sadd “user:101”, 1
    sadd “user:101”, 2
    sadd “user:102”, 1
    Sadd “user:102”, 3
    sinter “user:101” “user:101”

獲取到兩個用戶相似的產品, 然後確定相似產品的類目就可以進行用戶分析。
類似的應用場景還有, 社交場景下共同關注好友, 相似興趣 tag 等場景的支持。

2.3.4 Hash 類型使用場景

Redis 在存儲對象(例如:用戶信息)的時候需要對對象進行序列化轉換然後存儲。
還有一種形式,就是將對象數據轉換爲 JSON 結構數據,然後存儲 JSON 的字符串到 Redis。
對於一些對象類型,還有一種比較方便的類型,那就是按照 Redis 的 Hash 類型進行存儲。

hset key field value

例如,我們存儲一些網站用戶的基本信息, 我們可以使用:

hset user101  name “小明”
    hset user101  phone  “123456”
    hset user101  sex “男”

這樣就存儲了一個用戶基本信息,存儲信息有:{name : 小明, phone : “123456”,sex : “男”}
當然這種類似場景還非常多, 比如存儲訂單的數據,產品的數據,商家基本信息等。大家可以參考來進行存儲選型。

2.3.5 Sorted Set 類型使用場景

Redis sorted set 的使用場景與 set 類似,區別是 set 不是自動有序的,而 sorted set 可以通過提供一個 score 參數來爲存儲數據排序,並且是自動排序,插入既有序。
業務中如果需要一個有序且不重複的集合列表,就可以選擇 sorted set 這種數據結構。
比如,商品的購買熱度可以將購買總量 num 當做商品列表的 score,這樣獲取最熱門的商品時就是可以自動按售賣總量排好序。
sorted set 適合有排序需求的集合存儲場景。 大家可以思考一下自己負責的業務服務是否有可以使用的場景。

三、Redis 常見異常及解決方案

緩存使用過程當中,我們經常遇到的一些問題總結有四點:

3.1 緩存穿透

一般訪問緩存的流程,如果緩存中存在查詢的商品數據,那麼直接返回。 如果緩存中不存在商品數據, 就要訪問數據庫。

由於不恰當的業務功能實現,或者外部惡意攻擊不斷地請求某些不存在的數據內存,由於緩存中沒有保存該數據,導致所有的請求都會落到數據庫上,對數據庫可能帶來一定的壓力,甚至崩潰。
解決方案:
針對緩存穿透的情況, 簡單的對策就是將不存在的數據訪問結果, 也存儲到緩存中,避免緩存訪問的穿透。最終不存在商品數據的訪問結果也緩存下來。有效的避免緩存穿透的風險。

3.2 緩存雪崩

當緩存重啓或者大量的緩存在某一時間段失效, 這樣就導致大批流量直接訪問數據庫, 對 DB 造成壓力, 從而引起 DB 故障,系統崩潰。
舉例來說, 我們在準備一項搶購的促銷運營活動,活動期間將帶來大量的商品信息、庫存等相關信息的查詢。 爲了避免商品數據庫的壓力,將商品數據放入緩存中存儲。 不巧的是,搶購活動期間,大量的熱門商品緩存同時失效過期了,導致很大的查詢流量落到了數據庫之上。對於數據庫來說造成很大的壓力。
解決方案:

  1. 將商品根據品類熱度分類, 購買比較多的類目商品緩存週期長一些, 購買相對冷門的類目商品,緩存週期短一些;
  2. 在設置商品具體的緩存生效時間的時候, 加上一個隨機的區間因子, 比如說 5~10 分鐘之間來隨意選擇失效時間;
  3. 提前預估 DB 能力, 如果緩存掛掉,數據庫仍可以在一定程度上抗住流量的壓力

這三個策略能夠有效的避免短時間內,大批量的緩存失效的問題。

3.3 緩存預熱

緩存預熱就是系統上線後,將相關的緩存數據直接加載到緩存系統。這樣就可以避免在用戶請求的時候,先查詢數據庫,然後再將數據緩存的問題。用戶直接查詢事先被預熱的緩存數據。如圖所示:

如果不進行預熱, 那麼 Redis 初識狀態數據爲空,系統上線初期,對於高併發的流量,都會訪問到數據庫中, 對數據庫造成流量的壓力。
解決方案:

  1. 數據量不大的時候,工程啓動的時候進行加載緩存動作;
  2. 數據量大的時候,設置一個定時任務腳本,進行緩存的刷新;
  3. 數據量太大的時候,優先保證熱點數據進行提前加載到緩存。

3.4 緩存降級

降級的情況,就是緩存失效或者緩存服務掛掉的情況下,我們也不去訪問數據庫。我們直接訪問內存部分數據緩存或者直接返回默認數據。
舉例來說:

對於應用的首頁,一般是訪問量非常大的地方,首頁裏面往往包含了部分推薦商品的展示信息。這些推薦商品都會放到緩存中進行存儲,同時我們爲了避免緩存的異常情況,對熱點商品數據也存儲到了內存中。同時內存中還保留了一些默認的商品信息。如下圖所示:


降級一般是有損的操作,所以儘量減少降級對於業務的影響程度。

四、分佈式環境下常見的應用場景

4.1 分佈式鎖

當多個進程不在同一個系統中,用分佈式鎖控制多個進程對資源的操作或者訪問。 與之對應有線程鎖,進程鎖。
分佈式鎖可以避免不同進程重複相同的工作,減少資源浪費。 同時分佈式鎖可以避免破壞數據正確性的發生, 例如多個進程對同一個訂單操作,可能導致訂單狀態錯誤覆蓋。應用場景如下。

4.1.1 定時任務重複執行

隨着業務的發展,業務系統勢必發展爲集羣分佈式模式。如果我們需要一個定時任務來進行訂單狀態的統計。比如每 15 分鐘統計一下所有未支付的訂單數量。那麼我們啓動定時任務的時候,肯定不能同一時刻多個業務後臺服務都去執行定時任務, 這樣就會帶來重複計算以及業務邏輯混亂的問題。
這時候,就需要使用分佈式鎖,進行資源的鎖定。那麼在執行定時任務的函數中,首先進行分佈式鎖的獲取,如果可以獲取的到,那麼這臺機器就執行正常的業務數據統計邏輯計算。如果獲取不到則證明目前已有其他的服務進程執行這個定時任務,就不用自己操作執行了,只需要返回就行了。如下圖所示:

4.1.2 避免用戶重複下單

分佈式實現方式有很多種:

  1. 數據庫樂觀鎖方式
  2. 基於 Redis 的分佈式鎖
  3. 基於 ZK 的分佈式鎖

咱們這篇文章主要是講 Redis,那麼我們重點介紹基於 Redis 如何實現分佈式鎖。
分佈式鎖實現要保證幾個基本點。

  1. 互斥性:任意時刻,只有一個資源能夠獲取到鎖。
  2. 容災性:能夠在未成功釋放鎖的的情況下,一定時限內能夠恢復鎖的正常功能。
  3. 統一性:加鎖和解鎖保證同一資源來進行操作。

加鎖代碼演示:

public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String traceId, int expireTime) {
        SetParams setParams = new SetParams();
        setParams.ex(expireTime);
        setParams.nx();
        String result = jedis.set(lockKey, traceId, setParams);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

解鎖代碼演示:

public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String traceId) {
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(traceId));
            if (RELEASE_SUCCESS.equals(result)) {
                return true;
            }
            return false;
           }

4.2 分佈式自增 ID

應用場景
隨着用戶以及交易量的增加, 我們可能會針對用戶數據,商品數據,以及訂單數據進行分庫分表的操作。這時候由於進行了分庫分表的行爲,所以 MySQL 自增 ID 的形式來唯一表示一行數據的方案不可行了。 因此需要一個分佈式 ID 生成器,來提供唯一 ID 的信息。
實現方式
通常對於分佈式自增 ID 的實現方式有下面幾種:

  1. 利用數據庫自增 ID 的屬性
  2. 通過 UUID 來實現唯一 ID 生成
  3. Twitter 的 SnowFlake 算法
  4. 利用 Redis 生成唯一 ID

在這裏我們自然是說 Redis 來實現唯一 ID 的形式了。使用 Redis 的 INCR 命令來實現唯一 ID。
Redis 是單進程單線程架構,不會因爲多個取號方的 INCR 命令導致取號重複。因此,基於 Redis 的 INCR 命令實現序列號的生成基本能滿足全局唯一與單調遞增的特性。
代碼相對簡單, 不做詳細的展示了。

五、Redis 集羣模式

作爲緩存數據庫,肯定要考慮緩存服務穩定性相關的保障機制。
持久化機制就是一種保障方式。持久化機制保證了 Redis 服務器重啓的情況下也不會損失(或少量損失)數據,因爲持久化會把內存中數據保存到硬盤上,重啓會從硬盤上加載數據。
隨着 Redis 使用場景越來越多,技術發展越來越完善,在 Redis 整體服務上的容錯、擴容、穩定各個方面都需要不斷優化。 因此在 Redis 的集羣模式上也有不同的搭建方式來應對各種需求。
總結來說,Redis 集羣模式有三種:

  • 主從模式
  • 哨兵模式
  • Cluster 集羣模式

5.1 主從模式

爲了 Redis 服務避免單點故障,通常的做法是將 Redis 數據複製多個副本以部署在不同的服務器上。這樣即使有一臺服務器出現故障,其他服務器依然可以繼續提供服務。爲此,Redis 提供了複製( replication )功能,可以實現當一臺數據庫中的數據更新後,自動將更新的數據同步到其他數據庫上。
Redis 服務器分爲兩類:一類是主數據庫(Master),另一類是從數據庫(Slave)。
主數據庫可以進行讀寫操作,當寫操作導致數據變化時會自動將數據同步給從數據庫。
從數據庫一般是隻讀的,並接受主數據庫同步過來的數據。一個主數據庫可以擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。
如圖所示:

優點

  1. 一個主,可以有多個從,並以非阻塞的方式完成數據同步;
  2. 從服務器提供讀服務,分散主服務的壓力,實現讀寫分離;
  3. 從服務器之前可以彼此連接和同步請求,減少主服務同步壓力。

缺點

  1. 不具備容錯和恢復功能,主服務存在單點風險;
  2. Redis 的主從複製採用全量複製,需要服務器有足夠的空餘內存;
  3. 主從模式較難支持在線擴容。

5.2 哨兵模式

Redis 提供的 sentinel(哨兵)機制,通過 sentinel 模式啓動redis後,自動監控 Master/Slave 的運行狀態,基本原理是:心跳機制 + 投票裁決
簡單來說,哨兵的作用就是監控 Redis 系統的運行狀況。它的功能包括以下兩個:

  1. 監控主數據庫和從數據庫是否正常運行;
  2. 主數據庫出現故障時自動將從數據庫轉換爲主數據庫。

哨兵模式主要有下面幾個內容:

  • 監控( Monitoring ):Sentinel 會定期檢查主從服務器是否處於正常工作狀態。
  • 提醒( Notification ):當被監控的某個 Redis 服務器出現異常時,Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
  • 自動故障遷移(Automatic failover):當一個主服務器不能正常工作時,Sentinel 會開始一次自動故障遷移操作,它會將失效主服務器的其中一個從服務器升級爲新的主服務器,並讓失效主服務器的其他從服務器改爲複製新的主服務器;當客戶端試圖連接失效的主服務器時,集羣也會向客戶端返回新主服務器的地址, 使得集羣可以使用新主服務器代替失效服務器。

Redis Sentinel 是一個分佈式系統,你可以在一個架構中運行多個 Sentinel 進程( progress )。

優點

  1. 哨兵模式主從可以切換,具備基本的故障轉移能力;
  2. 哨兵模式具備主從模式的所有優點。

缺點

  1. 哨兵模式也很難支持在線擴容操作;
  2. 集羣的配置信息管理比較複雜。

5.3 Cluster 集羣模式

Redis Cluster 是一種服務器 Sharding 技術,3.0 版本開始正式提供。採用無中心結構,每個節點保存數據和整個集羣狀態,每個節點都和其他所有節點連接。如圖所示:

Cluster 集羣結構特點:

  1. Redis Cluster 所有的物理節點都映射到 [ 0-16383 ] slot 上(不一定均勻分佈),Cluster 負責維護節點、桶、值之間的關係;
  2. 在 Redis 集羣中放置一個 key-value 時,根據 CRC16(key) mod 16384 的值,從之前劃分的 16384 個桶中選擇一個;
  3. 所有的 Redis 節點彼此互聯(PING-PONG 機制),內部使用二進制協議優化傳輸效率;
  4. 超過半數的節點檢測到某個節點失效時則判定該節點失效;
  5. 使用端與 Redis 節點鏈接,不需要中間 proxy 層,直接可以操作,使用端不需要連接集羣所有節點,連接集羣中任何一個可用節點即可。

優點

  1. 無中心架構,節點間數據共享,可動態調整數據分佈;
  2. 節點可動態添加刪除,擴展性比較靈活;
  3. 部分節點異常,不影響整體集羣的可用性。

缺點

  1. 集羣實現比較複雜;
  2. 批量操作指令( mget、mset 等)支持有限;
  3. 事務操作支持有限。

六、Redis 常見面試題目詳解

1. 什麼是 Redis?

Redis 是一個基於內存的高性能 key-value 數據庫。支持多種數據類型。

2. 簡單描述一下 Redis 的特點有哪些?

Redis 本質上是一個 key-value 類型的內存數據庫,很像 memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據 flush 到硬盤上進行保存。
純內存操作,Redis 的性能非常出色,每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的 key-value DB。
Redis 的出色之處不僅僅是性能,Redis 最大的魅力是支持保存多種數據結構。
此外單個 value 的最大限制是 1GB,不像 memcached 只能保存 1MB 的數據,因此 Redis 可以用來實現很多有用的功能。
Redis 的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此 Redis 適合的場景主要侷限在較小數據量的高性能操作和運算上。

3. Redis支持的數據類型

Redis 通過 key-value 的單值不同類型來區分, 以下是支持的類型: String、List、Set、Sorted Set 、Hash。

4. 爲什麼 Redis 需要把所有數據放到內存中?

  1. 追求最快的數據讀取速度,如果直接磁盤讀取會非常慢;
  2. 爲了保證數據安全,也會異步方式將數據寫入磁盤;
  3. 可以設置 Redis 最大使用的內存,若達到內存限值後將不能繼續存入數據。

5. Redis 是單線程的嗎?

Redis是單線程處理網絡指令請求,所以不需要考慮併發安全問題。所有的網絡請求都是一個線程處理。但不代表所有模塊都是單線程。

6. Redis 持久化機制有哪些? 區別是什麼?優缺點是什麼?

Redis 提供兩種方式進行持久化。

  1. RDB 持久化:原理是將 Reids 在內存中的數據庫記錄定時 dump 到磁盤上的 RDB 持久化。
  2. AOF(append only file)持久化:原理是將 Redis 的操作日誌以追加的方式寫入文件。

兩者的區別:
RDB 持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是 fork 一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換之前的文件,用二進制壓縮存儲。

AOF 持久化以日誌的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。

RDB 優點

  1. RDB 是緊湊的二進制文件,比較合適備份,全量複製等場景;
  2. RDB 恢復數據遠快於 AOF。

RDB 缺點

  1. RDB 無法實現實時或者秒級持久化;
  2. 新老版本無法兼容 RDB 格式。

AOF 優點

  1. 可以更好地保護數據不丟失;
  2. appen-only 模式寫入性能比較高;
  3. 適合做災難性的誤刪除緊急恢復。

AOF 缺點:

  1. 對於同一份文件,AOF 文件要比 RDB 快照大;
  2. AOF 開啓後,寫的 QPS 會有所影響,相對於 RDB 來說 寫 QPS 要下降;
  3. 數據庫恢復比較慢, 不合適做冷備。

7. Redis 的緩存失效策略有哪幾種?

1) 定時刪除策略
在設置 key 的過期時間的同時,爲該 key 創建一個定時器,讓定時器在 key 的過期時間來臨時,對 key 進行刪除。

  • **優點:**保證內存儘快釋放。
  • **缺點:**若 key 過多,刪除這些 key 會佔用很多 CPU 時間, 而且每個 key 創建一個定時器,性能影響嚴重。

2) 惰性刪除策略
key 過期的時候不刪除,每次從數據庫獲取 key 的時候去檢查是否過期,若過期,則刪除,返回 null。

  • **優點:**CPU 時間佔用比較少。
  • **缺點:**若 key 很長時間沒有被獲取, 將不會被刪除,可能造成內存泄露。

3) 定期刪除策略
每隔一段時間執行一次刪除(在 redis.conf 配置文件設置 hz,1s 刷新的頻率)過期 key 操作。
**優點:**可以控制刪除操作的時長和頻率,來減少 CPU 時間佔用,可以避免惰性刪除時候內存泄漏的問題。
缺點:

  1. 對內存友好方面,不如定時策略
  2. 對 CPU 友好方面,不如惰性策略

Redis 一般採用:惰性策略 + 定期策略兩個相結合。

8. 什麼是緩存命中率?提高緩存命中率的方法有哪些?

  • **命中:**可以直接通過緩存獲取到需要的數據。
  • **不命中:**無法直接通過緩存獲取到想要的數據,需要再次查詢數據庫或者執行其它的操作。原因可能是由於緩存中根本不存在,或者緩存已經過期。

命中率越高表示使用緩存作用越好,性能越高(響應時間越短、吞吐量越高),併發能力也越好。
重點關注訪問頻率高且時效性相對低一些的業務數據上,利用預加載(預熱)、擴容、優化緩存粒度、更新緩存等手段來提高命中率。

七、總結

文章詳細向大家介紹了 Redis 相關的重要知識點,希望對大家以後的工作有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章