Redis 淘汰策略、持久化、高可用

淘汰策略

  • 只有 redis 內存空間已滿并且往里面寫新數據,才會觸發淘汰策略
  • 通過 expire / / /pexpire 讓 key-value 過期,從而讓 redis 清除這個 key-value。
  • value 的數據結構
    typedef struct redisObject {unsigned tpye:4;unsigned encoding:4;// 判斷哪些 key 要被刪除unsigned lru:LRU_BITS; // 占用 24位,8位用來記錄訪問的次數(0-255次),16位用來記錄上一次訪問的時間int refcount; // 引用計數void *ptr; // 指向 value 的存儲空間
    } robj;
    
    object idletime key # 展示 value 的 lru 字段
    
  • 配置淘汰策略
    • 如果 redis 內存空間已滿,并且沒有設置淘汰策略,再 set key value 會直接返回錯誤,提示內存空間已滿;如果設置了淘汰策略,redis 會按照淘汰策略選擇數據進行刪除,再 set key value 就會成功。
      # redis.conf
      maxmemory <bytes>  # redis 最多可以使用多少空間
      maxmemory-policy   # 淘汰策略,默認為 noeviction, 不進行淘汰
      maxmemory-samples  # 默認為 5,選擇多少個 key 進行淘汰
      
    • 過期 key 中
      • volatile-lru:最長時間沒有使用。
      • volatile-lfu:最少次數使用,隨機采樣。
      • volatile-ttl:最近要過期。
      • volatile-random:隨機。
    • 所有 key
      • allkeys-lru。
      • allkeys-lfu 。
      • allkeys-random 。
    • 禁止淘汰:no-eviction。

持久化

  • redis 為什么需要持久化 ?
    • 因為 redis 是內存數據庫,一旦關閉,內存中的數據就丟失了,所以需要把內存中的數據寫到磁盤中,這樣 redis 重啟后就可以從磁盤中加載原來的數據到內存中。
    • 只有寫操作(增刪改操作,會引起數據庫變更的操作)才會進行持久化。
  • redis 持久化方式
    • aof
      • 持久化的是寫操作協議內容(通過重放恢復內存中的數據),會有很多冗余數據;在 redis 進程中完成,every_sec 會另啟線程做持久化。
        *3
        $3
        set
        $4
        mark
        $1
        2
        
      • 策略
        • no:關閉 aof。
        • always:先將數據持久化到磁盤,再響應客戶端。(效率很低,一般不采用)
        • every_sec:只要內存修改成功,立刻響應客戶端。
          • 先將數據寫到 aof buffer 中,一秒后將 aof buffer 中的數據持久化到磁盤,這個過程是異步的,使用 bio_fsync_aof。
        • always 和 every_sec 會調用 fsync(fd) 將 page cache 中的數據立刻持久化到磁盤。 在這里插入圖片描述
      • aof-rewrite
        • 因為 aof 文件過大,數據恢復速度太慢,所以要減少 aof 文件大小。
        • 工作原理
          • fork 進程,根據內存數據生成 aof 文件,避免同一個 key 的歷史冗余數據。
          • 在重寫 aof 期間,對 redis 的寫操作會被記錄到重寫緩沖區,在重寫 aof 結束后,再將這些寫操作附加到 aof 文件末尾(可能有冗余數據)。
    • rdb
      • 持久化的是二進制數據(根據磁盤中的二進制數據恢復內存中的數據);另啟進程做持久化。
      • 工作原理:通過 fork 子進程進行持久化,基于內存中對象編碼直接持久化。
        • fork 相當于給父進程的內存做了一個快照。
        • fork 寫時復制
          在這里插入圖片描述
          • 頁表存儲了虛擬內存和物理內存之間的映射關系。
          • linux 為了加快 fork 的流程,fork 僅僅會復制頁表,然后將兩個頁表中的所有保護位修改為只讀,此時父進程和子進程共用一塊物理內存;父進程依然對外提供服務。
          • 當父進程處理寫操作時,首先會找到虛擬內存的內存頁,然后通過頁表寫物理內存頁的時候,發現保護位是只讀的,此時會觸發寫保護中斷:在物理內存中完成一次物理頁復制(把原來的物理頁復制一份),然后把數據寫入到復制后物理頁中,最后在寫保護中斷的處理函數中將頁表中的保護位修改為可讀可寫,并且重新構建頁表中的映射關系(頁表中該虛擬內存的指向變為新的物理頁)。
      • rdb-aof 混用
        • 通過 fork 子進程,根據內存數據生成 rdb 文件。
        • 在 rdb 持久化期間,對 redis 的寫操作會被記錄到重寫緩沖區,在 rdb 持久化結束后,采用 aof 的方式附加到文件末尾。
  • redis 持久化方式優缺點
    • aof
      • 優點:數據可靠,丟失較少;持久化過程代價較低(是順序磁盤 IO,持久化速度快)。
      • 缺點:aof 文件過大,數據恢復慢(通過重放恢復內存中的數據)。
    • rdb
      • 優點:rdb 文件小,數據恢復快。
      • 缺點:數據丟失較多;持久化過程代價較高。
  • 大 key 問題:kv 中,value 如果占用大量空間就是大 key,比如 value 是 hash、zset,里面存儲大量元素。
    • fsync 壓力大。
    • 因為頁表大,所以 fork 時間長,寫時復制造成持久化時間長。

高可用

  • 為什么實際業務中有高可用的需求 ?
    • 比如服務器依賴 redis,如果 redis 宕機了,那么服務器就不能給客戶端響應了,此時整個服務器處于不可用狀態。
    • redis 高可用:如果 redis 中的一個節點宕機了,會有備用節點頂替它,服務器不會因為 redis 中的一個節點宕機了,造成服務不可用。
  • 什么是高可用 ?
    • 在合理的時間內給出合理的回復。
      • 合理的時間:秒級的。
      • 合理的回復:給一個請求,如果發生錯誤,需要回復是到底是什么錯誤,不能模棱兩可。
  • 如何實現高可用 ?
    • 數據備份。
    • 節點切換策略。

主從復制

  • 主從復制不能保證高可用,只起到了數據備份的作用。
  • 含義
    • 主從復制是異步復制,服務器寫數據到主數據庫(master),主數據庫立刻返回;從數據庫(replica)不斷地從主數據庫中拉取數據并保存,以達到從數據庫和主數據庫數據一致。
    • replica 主動向 master 建立連接(否則無法線上新增 replica)
    • replica 主動向 master 拉取數據(若網絡出現問題,replica 持有同步位置:復制偏移量)
    • 缺點:可能帶來數據不一致:某一時刻如果從 replica 中獲取數據,數據可能不是最新的。
  • 實現
    在這里插入圖片描述
    在這里插入圖片描述
    • master 記錄了一個環形緩沖區和一個復制偏移量,replica 記錄了一個復制偏移量
    • RUN ID:
      • 無論 master 還是 replica 都有自己的 RUN ID,RUN ID 在其啟動時自動產生,由 40 個隨機的十六進制字符組成。
      • 當 replica 對 master 初次復制時,master 將自身的 RUN ID 發送給 replica,replica 會將 RUN ID 保存;當 replica 斷線重連 master 時,replica 將向 master 發送之前保存的 RUN ID。
      • 如果 replica RUN ID 和 master RUN ID 一致,說明 replica 斷線前復制的就是當前的 master,master 嘗試執行增量更新。若不一致,說明 replica 斷線前復制的 master 并不是當前的 master,則 master 將對 replica 執行全量更新
    • 復制偏移量 offset(64 位的整數且一直累加):
      • master 和 offset 都會維護一個復制偏移量;master 向 replica 發送 N 個字節的數據時,將自己的復制偏移量加上 N,replica 接收到 master 發送的 N 個字節的數據時,將自己的復制偏移量加上 N。
      • 如果 replica 記錄的復制偏移量在環形緩沖區中,就將 master 中的數據偏移和 replica 的數據偏移之間的數據發給 replica(增量更新)。
      • 如果 replica 記錄的復制偏移量不在環形緩沖區中,就把 master 中的 rdb 數據發給 replica(全量更新)。
      • 通過比較主從偏移量得知主從之間數據是否一致;偏移量相同則數據一致,偏移量不同則數據不一致。
      • 復制偏移量越大,數據越新

哨兵模式

在這里插入圖片描述

  • 哨兵模式是 redis 高可用的解決方案:
    • 由一個或多個 sentinel 實例構成 sentinel 集群,該集群可以監視任意多個主庫以及這些主庫所屬的從庫;當主庫處于下線狀態,會自動將該主庫所屬的某個數據最新的從庫升級為新的主庫。
    • 客戶端連接集群時,首先會連接 sentinel(任意一個 sentinel),通過 sentinel 來查詢主庫的地址(ip 地址 + 端口),并且通過 subscribe 監聽主庫切換,然后再連接主庫進行數據交互。
    • 當主庫發生故障時,sentinel 會主動推送新的主庫地址。這樣客戶端無須重啟即可自動完成節點切換。
  • 檢測異常
    • 主觀下線:sentinel 會以每秒一次的頻率向所有節點(其他 sentinel、主節點、從節點)發送 ping 消息,然后通過接收返回判斷該節點是否下線;如果配置指定了 down-after-milliseconds,則在該時間內沒有返回就被判斷為主觀下線。
    • 客觀下線:當一個 sentinel 節點將一個主節點判斷為主觀下線之后,為了確
      認這個主節點是否真的下線,它會向其他 sentinel 節點進行詢問,如果收到一定數量(半數以上)的已下線回復,sentinel 會將主節點判定為客觀下線,并通過領頭 sentinel 節點對主節點執行故障轉移。
    • 故障轉移:
      • 從節點中選舉一個節點作為新的主節點(選復制偏移量最大的從節點)。
      • 通知其他從節點復制連接新的主節點。
      • 若故障主節點重新連接,將作為新的主節點的從節點。
  • 缺點:
    • 延遲較大:redis 采用異步復制的方式,意味著當主節點掛掉時,從節點可能沒有收到全部的同步消息,這部分未同步的消息將會丟失。如果主從延遲特別大,那么丟失可能會特別多。
    • 不能進行數據擴容
    • 部署麻煩。
  • 配置
    # sentinel.cnf
    # sentinel 只需指定檢測主節點就行了,通過主節點自動發現從節點
    sentinel monitor mymaster 127.0.0.1 6379 2
    # 判斷主觀下線時長
    sentinel down-after-milliseconds mymaster 30000
    # 指定可以有多少個 redis 服務同步新的主機,一般而言,這個數字越小同步時間越長; 越大,則對網絡資源要求越高
    sentinel parallel-syncs mymaster 1
    # 指定故障切換允許的毫秒數,超過這個時間,就認為故障切換失敗,默認為 3分鐘
    sentinel failover-timeout mymaster 180000
    

cluster 集群

在這里插入圖片描述

  • 實現高可用
    • 數據備份:每個主節點都會有多個從節點。
    • 主節點轉移:集群節點間會互相發送消息,交換節點的狀態信息;若某主節點下線,將會被其它節點標記下線,接著在該下線主節點的從節點中選擇一個數據最新的從節點作為主節點;從節點繼承下線主節點的槽位信息,并廣播改消息給集群中的其它節點。
  • 特征:
    • 去中心化:沒有中心節點。
    • 主節點對等。
    • 能夠進行數據擴容。
    • 讀寫數據只會通過主節點進入集群。
  • 流程:
    1. 連接集群中任意一個節點。
    2. 若數據不在該節點,將收到連接切換的命令,繼而連接到目標節點。
  • 缺點:因為主從采用異步復制,在主節點轉移時仍存在數據丟失的情況。
  • 配置集群 在這里插入圖片描述
# 創建 6 個文件夾
mkdir -p 7001 7002 7003 7004 7005 7006
cd 7001
vi 7001.conf# 7001.conf 中的內容如下
pidfile "/home/zcoder/redis-cluster/7001/7001.pid"
logfile "/home/zcoder/redis-cluster/7001/7001.log"
dir /home/zcoder/redis-cluster/7001/
port 7001
daemonize yes
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 15000# 復制配置
cp 7001/7001.conf 7002/7002.conf
cp 7001/7001.conf 7003/7003.conf
cp 7001/7001.conf 7004/7004.conf
cp 7001/7001.conf 7005/7005.conf
cp 7001/7001.conf 7006/7006.conf# 查看目錄結構
tree .# 修改配置
sed -i 's/7001/7002/g' 7002/7002.conf
sed -i 's/7001/7003/g' 7003/7003.conf
sed -i 's/7001/7004/g' 7004/7004.conf
sed -i 's/7001/7005/g' 7005/7005.conf
sed -i 's/7001/7006/g' 7006/7006.conf
#!/bin/bash
# 創建啟動配置 start.sh
redis-server 7001/7001.conf
redis-server 7002/7002.conf
redis-server 7003/7003.conf
redis-server 7004/7004.conf
redis-server 7005/7005.conf
redis-server 7006/7006.conf
# 增加可執行權限
chmod +x start.sh # 啟動全部 redis 節點 
./start.sh
# 查看 redis 節點是否全部啟動
ps aux | grep redis-server# 智能創建 redis 集群
# --cluster-replicas: 一個主節點對應幾個從節點
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1

在這里插入圖片描述

# 讀寫數據只會通過主節點進入集群
# 進入指定的 redis 節點
redis-cli -c -p 7006 # 127.0.0.1:7006
set zcoder 1         # 會重定向到存儲該數據的主節點
# 主節點宕機
redis-cli -p 7001 shutdown
# 主節點重啟
redis-server 7001/7001.conf
  • 使用 crc16(zcoder) % 16384,通過增大樣本數,讓各個主節點存儲的數據量較為均衡。
    在這里插入圖片描述
  • 擴容:先增加節點,再分配槽位。
    cp -R 7001 7007
    cd 7007
    mv 7001.conf 7007.conf
    rm 7001.log dump.rdb nodes-7001.conf
    sed -i "s/7001/7007/g" 7007.conf
    cp -R 7007 7008
    cd 7008
    mv 7007.conf 7008.conf
    sed -i "s/7007/7008/g" 7008.conf
    cd ..
    redis-server 7007/7007.conf
    redis-server 7008/7008.conf
    # 7007 是主節點,7008 是從節點
    redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001 
    redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave --cluster-master-id 主節點的id# 將槽位重新分配到整個集群的所有節點中
    redis-cli --cluster reshard 127.0.0.1:7001
    How many slots do you want to move (from 1 to 16384)? #1000
    What is the receiving node ID? # 主節點的id
    Please enter all the source node IDs.
    Type 'all' to use all the nodes as source nodes for the hash slots.
    Type 'done' once you entered all the source nodes IDs.
    Source node # all# 將節點 A 的槽位遷移到節點 B
    redis-cli --cluster reshard 127.0.0.1:7001 --cluster-from 節點A的id --cluster-to 節點B的id --cluster-slots 1000
    
  • 縮容:先移動槽位,再刪除節點
    redis-cli --cluster reshard 127.0.0.1:7001 --cluster-from 節點B的id --cluster-to 節點A的id --cluster-slots 1000
    # 刪除節點 7007
    redis-cli --cluster del-node 127.0.0.1:7001 節點7007的id
    # 此時 7008 成為其他節點的從節點
    redis-cli --cluster del-node 127.0.0.1:7001 節點7008的id
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/719319.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/719319.shtml
英文地址,請注明出處:http://en.pswp.cn/news/719319.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

個人數倉開發面試題記錄

一.廣州電商公司 1.簡單自我介紹 2.介紹下之前的公司離線數倉項目 3.mysql和hive區別&#xff1f; 4.sql的執行順序&#xff1f; 5.hive的優化 6.說下你之前公司來&#xff0c;你的技能層次在每個公司&#xff1f;你怎么評價你的技能&#xff1f; 7.你的之前業務主要是做什么&…

Linux基礎命令[10]-cmp

文章目錄 1. cmp 命令說明2. cmp 命令語法3. cmp 命令示例3.1 不加參數3.2 -b&#xff08;顯示不同的字節&#xff09;3.3 -i&#xff08;跳過字節&#xff09;3.4 -l&#xff08;顯示所有不同&#xff09;3.5 -n&#xff08;比較n個字節&#xff09;3.6 -s&#xff08;不顯示信…

el-select 不能重復選擇

el-select 不能重復選擇&#xff0c;注意&#xff1a;刪除后可以再次重新被選擇 <el-form-item><el-select v-model"attribute.attributeSelect" change"changeSelect()" placeholder"請選擇屬性分組" clearable><el-optionv-fo…

PostgreSQL restartpoint 原理詳解

背景 大部分人對 PG 的 checkpoint 機制會熟悉一點&#xff0c;但是對 restartpoint 卻不太熟悉&#xff0c;網上介紹這方面的文章也比較少。因此&#xff0c;本文將以 PG 14.7 的社區代碼為基礎&#xff0c;介紹 PG 中的 restartpoint 機制。 原理介紹 什么是 restartpoint…

華為OD技術面試案例1-2024年

背景&#xff1a; 學校背景&#xff1a;211本科工作經驗&#xff1a;1年半轉行目標&#xff1a;測試崗位 一、機考 &#xff08;得分&#xff1a;350&#xff09; 二、01.04 hr面 自我介紹選擇東莞的原因對OD&#xff08;華為研發崗位&#xff09;的看法家庭情況簡歷相關問…

信息論筆記:信息量+熵+相對熵+交叉熵+損失函數

信息論 信息量 I(x) -log( P )I為信息量P為x發生的概率 熵 混亂程度的度量&#xff0c;不確定的局面表示很混亂系統里信息量的期望值H(x) -sum( P(i) * log( P(i) ) ) 相對熵(KL散度) 用于度量兩個概率分布間的差異性信息D_KL(S | O) sum( P_S(x) * log_2( 1 / P_O(x)…

Mysql學習之各種鎖

鎖 事務的隔離性由鎖來實現 MySQL并發事務訪問相同記錄 并發事務訪問相同記錄的情況大致可以分為3種&#xff1a; 讀-讀的情況 讀-讀情況&#xff0c;即并發事務相繼讀取相同的記錄。讀取操作本身不會對記錄由有任何的影響&#xff0c;并不會引起什么問題&#xff0c;所以允許…

簡要講解OV7725攝像頭

本文主要包含以下幾部分內容&#xff1a; 1. 通過OV7725分析模塊原理圖。 2. 講解部分寄存器的含義、RGB565格式圖像輸出時序、幀率計算。 3. 講解SCCB協議與I2C協議的區別。 1、OV7725功能 OV7725是一款1/4英寸單芯片圖像傳感器&#xff0c;其感光陣列達到640*480&#xff0c…

LibreOJ 137. 最小瓶頸路(加強版) 題解 Kruscal重構樹 ST表

聲明&#xff1a;本題目是LibreOJ 136. 最小瓶頸路 題解 最小生成樹 倍增加強版&#xff0c;建議先學習簡單版的做法。 題目鏈接&#xff1a;LibreOJ 137. 最小瓶頸路&#xff08;加強版&#xff09; 題目描述&#xff1a; 給定一張無向圖&#xff0c;詢問兩個結點之間的最小瓶…

【MySQL 系列】在 Windows 上安裝 MySQL

在 Windows 平臺上安裝 MySQL 很簡單&#xff0c;并不需要太復雜的步驟。按照本文的步驟操練起來就可以了。 文章目錄 1、下載 MySQL 安裝程序2、安裝 MySQL 數據庫2.1、選擇安裝類型2.2、檢查所需組件2.3、安裝所選產品組件2.4、產品配置2.5、配置高可用性2.6、配置服務器類型…

【leetcode】 劍指 Offer學習計劃(java版本含注釋)(下)

目錄 前言第十六天&#xff08;排序&#xff09;劍指 Offer 45. 把數組排成最小的數&#xff08;中等&#xff09;劍指 Offer 61. 撲克牌中的順子&#xff08;簡單&#xff09; 第十七天&#xff08;排序&#xff09;劍指 Offer 40. 最小的k個數&#xff08;簡單&#xff09; 第…

c++11多線程:call_once

文章目錄 call_once示例一示例二 call_once std::call_once是 C11 標準庫中的一個函數&#xff0c;用于確保某個函數只會被調用一次。 單例設計模式是一種常見的設計模式&#xff0c;用于確保某個類只能創建一個實例。由于單例實例是全局唯一的&#xff0c;因此在多線程環境中…

YOLO系列中的“data.yaml”詳解!

專欄介紹&#xff1a;YOLOv9改進系列 | 包含深度學習最新創新&#xff0c;主力高效漲點&#xff01;&#xff01;&#xff01; 一、data.yaml介紹 YOLO系列中的data.yaml文件包含了YOLO系列模型運行所需要的數據集路徑、數據集中的類別數及標簽。數據集路徑可以用絕對路徑也可以…

Python實現股票信息查詢

目前兩個常用的股票信息CPI&#xff1a; 騰訊行情CTPAPI接口源碼 新浪行情CTPAPI 使用requests模塊爬取股票信息&#xff0c;這里以查詢股票市值為例。 一、根據股票名稱查詢股票代碼 在python文件夾下設置兩個表格GPLIST.xlsx&#xff0c;其中是A股全部代碼和股票名稱&#…

如何在飛書接入ChatGPT并結合內網穿透實現公網遠程訪問智能AI助手

文章目錄 前言環境列表1.飛書設置2.克隆feishu-chatgpt項目3.配置config.yaml文件4.運行feishu-chatgpt項目5.安裝cpolar內網穿透6.固定公網地址7.機器人權限配置8.創建版本9.創建測試企業10. 機器人測試 前言 在飛書中創建chatGPT機器人并且對話&#xff0c;在下面操作步驟中…

MySQL 高可用解決方案(雙主雙從)

1.環境說明 操作系統&#xff1a;centos7.7 主服務器&#xff1a;node2(192.168.1.102) 從服務器&#xff1a;node3(192.168.1.103) keepalived中虛擬ip(VIP):192.168.1.100 2.準備事項 主庫和從庫數據庫的版本一致把主庫的數據同步給從庫一份 #對主庫進行全局讀鎖定 FLUSH…

GEE代碼條帶問題——sentinel-1接縫處理的問題

問題 我有興趣確定 NDVI 損失最大的年份。我創建了一個函數來收集所有陸地衛星圖像并應用預處理。當我導出結果以識別 NDVI 損失最大年份時&#xff0c;生成的數據產品與陸地衛星場景足跡有可怕的接縫線。造成這種情況的原因是什么以及如何調整代碼&#xff1f; sentinel1數據…

flutter之終極報錯

看到這個報錯頭都大了 一開始在網上各種搜搜&#xff0c;然后有人說是flutter版本的問題&#xff0c;改完版本之后還是不對&#xff0c;又是各種搜搜搜 有人說是環境變量的問題&#xff0c;后來改了環境變量&#xff0c;媽的&#xff0c;竟然還不行&#xff0c;想砸電腦的心都…

Xcode :Could not build module ‘WebKit‘ 已驗證解決

問題&#xff1a;Could not build module WebKit 具體報錯如下&#xff1a; error: type argument nw_proxy_config_t (aka struct nw_proxy_config *) is neither an Objective-C object nor a block type property (nullable, nonatomic, copy) NSArray<nw_proxy_config_…

C++學習筆記:set和map

set和map set什么是setset的使用 關聯式容器鍵值對 map什么是mapmap的使用map的插入方式常用功能map[] 的靈活使用 set 什么是set set是STL中一個底層為二叉搜索樹來實現的容器 若要使用set需要包含頭文件 #include<set>set中的元素具有唯一性(因此可以用set去重)若用…