天天看點

Redis持久化實作

文章目錄

      • 一. Redis
          • 1.1 文法回顧
          • 1.2 事務
          • 1.3 持久化 (重點)
            • 1.3.1 RDB 快照存儲
            • 1.3.1 AOF 隻追加檔案
            • 1.3.3 如何選擇
          • 1.4 分布式設計
            • 1.4.1 哨兵 (重點)
            • 1.4.2 叢集

一. Redis

1.1 文法回顧
  • String
    • 記錄字元串/整數/浮點數
    • 指令
      • set 添加/修改資料
      • get 擷取資料
      • mset 添加多個資料
      • mget 擷取多個資料
      • incr 計數加1
      • decr 計數減1
      • incrby 計數加n
  • 鍵指令
    • 适用于所有的類型
    • 指令
      • del 删除資料
      • exists 判斷資料是否存在
      • expire 設定過期時間
      • ttl 擷取剩餘時間
      • keys 查詢滿足條件的鍵
  • hash
    • 類似

      字典

      的結構
    • 指令
      • hset 添加字段
      • hget 擷取字段
      • hmset 添加多個字段
      • hmget 擷取多個字段
      • hdel 删除字段
  • list
    • 是一個

      雙向連結清單

    • 指令
      • lpush 從左側追加元素
      • lrange 從左側周遊元素
      • rpush 從右側追加元素
      • lset 從左側修改元素
      • lpop 從左側删除元素
      • rpop 從右側删除元素
      • ltrim 裁切清單
  • zset
    • 有序

      集合, 按照分數(score)進行排序
    • 指令
      • zadd 添加/修改元素
      • zrange 周遊元素(按分數從小到大)
      • zrevrange 反向周遊元素(從大到小)
      • zrangebyscore 周遊指定分數範圍的元素
      • zscore 查詢元素的分數
      • zrem 删除元素
      • zincrby 元素的分數計數加n
  • set
    • 無序

      集合 無序+去重
    • 指令
      • sadd 添加元素
      • smembers 周遊元素
      • sismember 判斷是否包含
      • srem 删除元素
  • redis-py
    • python中獨立的redis包
    • 安裝

      pip install redis

Redis持久化實作
1.2 事務
  • 文法
    • MULTI
      • 開啟事務, 後續的指令會被加入到同一個事務中
      • 事務中的操作會發給服務端, 但是不會立即執行, 而是放到了該事務的對應的一個隊列中, 服務端傳回QUEUED
    • EXEC
      • 執行EXEC後, 事務中的指令才會被執行
      • 事務中的指令出現錯誤時,

        不會復原也不會停止事務

        , 而是繼續執行
    • DISCARD
      • 取消事務, 事務隊列會清空, 用戶端退出事務狀态
  • ACID
    • 原子性
      • 不支援
      • 不會復原并且繼續執行
    • 隔離性
      • 支援
      • 事務中指令順序執行, 并且不會被其他用戶端打斷 (先EXEC的先執行)
    • 持久性
      • 不支援, redis資料易丢失
    • 一緻性
      • 不支援
      • 強一緻性要求 通過樂觀鎖(watch)來實作
Redis持久化實作
  • WATCH
    • redis實作的樂觀鎖
    • 機制
      • 事務開啟前, 設定對資料的監聽, EXEC時, 如果發現資料發生過修改, 事務會自動取消(DISCARD)
      • 事務EXEC後, 無論成敗, 監聽會被移除
# 解決更新丢失問題
WATCH mykey  # 監視mykey的值
GET mykey  # 讀取資料, 假設需要進行*2操作, 再将結果重新指派 (假設取出5)
MULTI  # 開啟事務
SET mykey 10
EXEC  # 如果mykey的值在執行exec之前發生過改變, 則該事務會取消(用戶端可以在發生碰撞後不斷重試)
           
Redis持久化實作
如果隻是加減操作, 建議使用

incr類

的操作, 單一操作具有原子性
  • 流水線
Redis持久化實作
1.3 持久化 (重點)

1.3.1 RDB 快照存儲

  • 記憶體中的所有資料

    完整的儲存到硬碟中
  • 機制
    • fork出一個

      子程序

      ,專門進行資料持久化, 将記憶體中所有資料儲存到單個rdb檔案中(預設為dump.rdb)
    • redis重新開機後, 會加載rdb檔案中的資料到記憶體中
  • 觸發方式
    • 配置中設定

      自動持久化政策

    • SAVE

      |

      BGSAVE

      |

      SHUTDOWN

      (前提是設定了自動持久化政策)
  • 相關配置
save 60 1000  # 多久執行一次自動快照操作 60秒内如果更新了1000次, 則持久化一次
  stop-writes-on-bgsave-error no  # 建立快照失敗後,是否繼續執行寫指令
  rdbcompression yes  # 是否對快照檔案進行壓縮
  dbfilename dump.rdb  # 如何命名快照檔案
  dir ./ # 快照檔案儲存的位置

  save   # 關閉RDB機制
           
  • 優缺點
    • 優點
      • 友善資料備份

        : 由于儲存到

        單獨的檔案

        中, 易于資料備份 (可以使用定時任務, 定時将檔案發送給資料備份中心)
      • 寫時複制

        : 子程序單獨完成持久化操作, 父程序不參與IO操作, 最大化redis性能
      • 恢複大量資料時, 速度優于 AOF
    • 缺點
      • 不是實時儲存資料

        , 如果redis意外停止工作(如電源斷電等), 則可能會丢失一段時間的資料
      • 資料量大時, fork程序會比較慢, 持久化時使redis響應速度變慢

1.3.1 AOF 隻追加檔案

  • Append-only file 隻追加檔案
    • 隻追加

      而 不是全部重新寫入
    • 追加指令

      , 而不是資料
  • 機制
    • 主線程将

      寫指令

      追加到aof_buf(緩沖區)中, 根據使用的政策不同,

      子線程

      将緩存區的指令寫入到aof檔案中 (不使用子程序)
    • 當redis重新開機時, 會重新執行aof檔案中的指令來恢複資料
      • 如果同時開啟了 RDB, 則優先使用 AOF
  • 檔案修複
    • 如果AOF出錯 (磁盤滿了/寫入中途當機等), 則redis重新開機時會拒絕使用該AOF檔案
    • 修複步驟
      • 首先備份AOF檔案
      • 使用redis-check-aof工具進行修複 (一般會删除末尾無法恢複的指令)
      • 重新開機redis伺服器, 自動載入修複後的AOF檔案, 進行資料恢複
    $ redis-check-aof –fix
    # 可選操作: 使用 diff -u 對比修複後的 AOF 檔案和原始 AOF 檔案的備份,檢視兩個檔案之間的不同之處。
               
  • 檔案重寫/壓縮
    • AOF 提供了重寫/壓縮機制(優化指令), 以避免AOF檔案過大
    • fork子程序來完成 AOF 重寫
  • 相關配置
appendonly no  # 是否開啟AOF機制
appendfsync everysec  # 多久将寫入的内容同步到硬碟 每秒一次
no-appendfsync-on-rewirete no  # 重寫aof檔案時是否執行同步操作
auto-aof-rewrite-percentage 100  # 多久執行一次aof重寫, 當aof檔案的體積比上一次重寫後的aof檔案大了一倍時
auto-aof-rewrite-min-size 64mb  # 多久執行一次aof重寫,當aof檔案體積大于64mb時

appendfilename appendonly.aof  # aof檔案名
dir ./  # aof檔案儲存的位置(和rdb檔案共享該配置)
           
  • 優缺點
    • 優點

      -

      更可靠

      預設每秒同步一次操作, 最多丢失一秒資料

      - 提供了三種政策, 還可以不同步/每次寫同步

      - 可以進行`檔案重寫`, 以避免AOF檔案過大
                 
    • 缺點

      - 相同資料集, AOF檔案比RDB

      體積大

      ,

      恢複速度慢

      - 除非是不同步情況, 否則普遍要比RDB

      速度慢

1.3.3 如何選擇

  • 對于

    更新頻繁, 一緻性要求不是非常高的資料

    可以選擇使用redis進行持久化存儲
  • RDB or AOF
    • 資料安全性要求高, 都打開
    • 可以接受短時間的資料丢失, 隻使用 RDB
    • 即使使用 AOF, 最好也開啟 RDB, 因為便于備份并且回複速度快, bug更少
  • 項目中的應用
    • 使用redis進行一部分資料的持久化存儲
      • 使用者的閱讀曆史
    • 兩種持久化機制都開啟了
1.4 分布式設計

1.4.1 哨兵 (重點)

  • 作用
    • 監控redis伺服器的運作狀态, 可以進行

      自動故障轉移

      (failover), 實作高可用
    • 資料庫主從

      配合使用的機制
  • 特點
    • 獨立的程序, 每台redis伺服器應該至少配置一個哨兵程式
    • 監控redis主伺服器的運作狀态
    • 出現故障後可以向管理者/其他程式發出通知
    • 針對故障,可以進行自動轉移, 并向用戶端提供新的通路位址
  • 流言協定

    - 當某個哨兵程式 發現監視的主伺服器下線後(心跳檢測), 會向監聽該伺服器的其他哨兵詢問, 是否确認主伺服器下線, 當 确認的哨兵數量 達到要求(配置檔案中設定)後, 會确認主伺服器下線(客觀下線), 然後進入投票環節

  • 投票協定

    - 當确認主伺服器客觀下線後, 哨兵會通過 投票的方式 來授權其中一個哨兵主導故障轉移處理

    - 隻有在 大多數哨兵都參加投票 的前提下, 才會進行授權, 比如有5個哨兵, 則需要至少3個哨兵投票才可能授權

    - 目的是避免出現錯誤的故障遷移

  • 建議最低配置

    - 至少在3台伺服器上分别啟動至少一個哨兵

    - 如果隻有一台, 則伺服器當機後, 将無法進行故障遷移

    - 如果隻有兩台, 一旦一個哨兵挂掉了, 則投票會失敗

  • 相關配置 (sentinel.conf)
bind 127.0.0.1  # 哨兵綁定的ip
port 26381  # 哨兵監聽的端口号, redis用戶端需要通路哨兵的ip和端口号
sentinel monitor mymaster 127.0.0.1 6380 2  # 設定哨兵  (主資料庫别名 主資料庫ip 主資料庫端口 确認下線的最小哨兵數量)

sentinel down-after-milliseconds mymaster 60000  # 伺服器斷線逾時時長
sentinel failover-timeout mymaster 180000  # 故障轉移的逾時時間
sentinel parallel-syncs mymaster 1  # 執行故障轉移時,最多幾個從資料庫可以同步主資料庫資料(數量少會增加完成轉移的時長;數量多可能會影響主資料庫的資料查詢)

min-slaves-to-write 2  # 可執行故障轉移的從資料庫的最小數量(低于當數量時, 主資料庫将禁止寫入操作)
min-slaves-max-lag 10  # 從資料庫的最大響應時長 
# 以上兩條連起來: 當至少有2個從資料庫可以進行複制并且響應延遲都在10秒之内時, 主資料庫才允許寫操作	
           
  • 啟動哨兵
redis-sentinel sentinel.conf
           
Redis持久化實作
mysql官方沒有提供故障轉移方案, 需要用第三方的服務, 如 keepalive等

1.4.2 叢集

  • 多個節點共同儲存資料
  • 作用
    • 拓展存儲空間
    • 提高吞吐量, 提高寫能力
  • 和單機的不同點
    • 不再區分資料庫, 隻有0号庫, 單機預設0-15
    • 不支援事務/管道/多值操作
    • 叢集預設就內建了哨兵, 至少三主三從, 自動故障轉移
  • 安裝

    pip install redis-cluster

Redis持久化實作
  • 項目中的使用
    • 主從配置了哨兵和持久化機制, 用于儲存使用者的閱讀曆史
    • 叢集負責實作緩存設計