redis

Redis 技術棧

安裝

yum & apt

  • apt-get install Redis-server
  • yum install Redis

編譯

  1. 下載
  • wget http://download.Redis.io/releases/Redis-5.0.5.tar.gz
  1. 編譯
  tar -zxvf Redis-5.0.5.tar.gz
  cd Redis-5.0.5
  make && make install
  1. 配置
  • vim Redis.conf
  1. 啓動
  • Redis-server
  1. 關閉
  • Redis-cli shutdown

key 命令

keys

  • 搜索key根據匹配模式,例如: keys *

exists

  • 判斷key是否存在,存在返回1,不存在返回0

del

  • 刪除key

type

  • 獲取key類型

randomkey

  • 隨機返回key

expire

  • 設置key過期時間

sortzh

  • 字符串排序
  • 數字排序

服務端命令

flushall

  • 強制清空所有key(目標對象所有數據庫)

flushdb

  • 清空當前數據庫

client list

  • 連接信息列表

client kill

  • 關閉ip:port客戶端

ping

  • 判斷是否正常運行,正常運行返回pong

數據類型(操作命令非完整)

string

  • 一個key最大存儲512M的數據

操作方法

  • get /set(單key操作)
  • mget / mset(多key操作)
  • getrange 獲取指定下標範圍內的字符串
  • setrange 設置指定下標範圍內的字符串
  • setex => set expire 組合
  • incr 自增1
  • incrby 自增指定數字
  • decr 自減1
  • decrby 自減指定數字
  • append 追加字符串
  • strlen 返回字符串長度

list

  • blpop key 刪除並獲取第一個元素
  • brpop key 刪除並獲取最後一個元素
  • brpoplpush source destination 複製列表從source -> destination
  • lindex key index 根據key 和index 獲取value
  • llen key 獲取key的列表長度
  • lpop key 從左側出列
  • lpush key value 從左側入列
  • lrange key start stop 根據start,stop獲取key一定範圍內的列表
  • lset key index value 根據key + index 設置value
  • lrem key count value 刪除列表元素
  • rpush等不做贅述

set

  • sadd key value 向key插入值
  • scard key 獲取集合成員數量
  • sdiff key1 key2 返回集合差集
  • sinter key1 key2 返回集合交集
  • sunion key1 key2 返回集合並集
  • sismember key value 判斷集合中是否包含value
  • smembers key 返回集合
  • srem key value 刪除集合中的一個value

hash

  • hget key filed 獲取hash中指定key->filed的值
  • hgetall key 獲取hash中指定key的所有制
  • hexists key filed 查看是否存在filed
  • hdel key filed 刪除指定key下的filed
  • hkeys key 獲取所有filed
  • hset key filed value 設置key->filed->value

sortedSet

  • zadd key source member 向key追加source,member
  • zcard key 獲取成員數量

數據存儲(持久化)

RDB

將某個時間點的所有數據都以二進制形式存放到硬盤上

  • 可以將快照複製到其它服務器從而創建具有相同數據的服務器副本.
  • 如果系統發生故障,將會丟失最後一次創建快照之後的數據.
  • 如果數據量很大,保存快照的時間會很長,建議異步寫入.
  • 存在的問題:時間、性能開銷大,不可控且容易丟失數據.
  • 同步機制
    • save 命令,阻塞其他命令,直到save命令結束
    • bgsave 命令,異步化,創建子線程進行持久化,不會阻塞其他命令
  • 自動化觸發
    • 根據修改數量、時間進行命令執行
    • save 900 1 # 900秒之內,對數據庫進行了一次修改就執行 bgsave 命令
    • save 300 10 # 300秒之內,對數據庫進行了十次修改就執行 bgsave 命令
    • save 60 10000 # 60秒之內,對數據庫進行了一萬次修改就執行 bgsav e命令

AOF

將寫命令添加到 AOF 文件(Append Only File)的末尾(MySQL Binlog、HBase HLog).

  • 隨着服務器寫請求的增多,AOF 文件會越來越大.Redis 提供了一種將 AOF 重寫的特性,能夠去除 AOF 文件中的冗餘寫命令
  • 使用 AOF 持久化需要設置同步選項,從而確保寫命令什麼時候會同步到磁盤文件上.這是因爲對文件進行寫入並不會馬上將內容同步到磁盤上,而是先存儲到緩衝區,然後由操作系統決定什麼時候同步到磁盤.

同步機制

  • always 每個命令都同步
  • eversec 每秒同步
  • no 操作系統決定同步時間

AOF重寫

  • 對多條原生命令進行優化,重寫成簡化的命令以減少磁盤佔用量、提高故障恢復效率.
  • 當 AOF 文件過大或增長速度過快時自動觸發
  • 配置
    • auto-aof-rewrite-min-size:AOF 文件重寫需要的大小

    • auto-aof-rewrite-percentage:AOF 文件增長率

    • aofcurrentsize:AOF 當前大小

    • aof-base-size:AOF 上次啓動和重寫的大小

  • 觸發條件
    • aof_current_size > auto-aof-rewrite-min-size
    • aof_current_size - aof_base_size/aof_base_size > auto-aof-rewrite-percentage

集羣

主從複製

主從鏈(拓撲結構)

主從

主從

複製模式

  • 全量複製:master 全部同步到 slave
  • 部分複製:slave 數據丟失進行備份

問題點

  • 同步故障
    • 複製數據延遲(不一致)
    • 讀取過期數據(Slave 不能刪除數據)
    • 從節點故障
    • 主節點故障
  • 配置不一致
    • maxmemory 不一致:丟失數據
    • 優化參數不一致:內存不一致.
  • 避免全量複製
    • 選擇小主節點(分片)、低峯期間操作.
    • 如果節點運行 id 不匹配(如主節點重啓、運行 id 發送變化),此時要執行全量複製,應該配合哨兵和集羣解決.
    • 主從複製擠壓緩衝區不足產生的問題(網絡中斷,部分複製無法滿足),可增大複製緩衝區( rel_backlog_size 參數).
  • 複製風暴

哨兵機制

拓撲圖

image

節點下線

  • 客觀下線
    • 所有 Sentinel 節點對 Redis 節點失敗要達成共識,即超過 quorum 個統一.
  • 主管下線
    • 即 Sentinel 節點對 Redis 節點失敗的偏見,超出超時時間認爲 Master 已經宕機.

leader選舉

  • 選舉出一個 Sentinel 作爲 Leader:集羣中至少有三個 Sentinel 節點,但只有其中一個節點可完成故障轉移.通過以下命令可以進行失敗判定或領導者選舉.
  • 選舉流程
    1. 每個主觀下線的 Sentinel 節點向其他 Sentinel 節點發送命令,要求設置它爲領導者.
    2. 收到命令的 Sentinel 節點如果沒有同意通過其他 Sentinel 節點發送的命令,則同意該請求,否則拒絕.
    3. 如果該 Sentinel 節點發現自己的票數已經超過 Sentinel 集合半數且超過 quorum,則它成爲領導者.
    4. 如果此過程有多個 Sentinel 節點成爲領導者,則等待一段時間再重新進行選舉.

故障轉移

  • 轉移流程
    1. Sentinel 選出一個合適的 Slave 作爲新的 Master(slaveof no one 命令).
    2. 向其餘 Slave 發出通知,讓它們成爲新 Master 的 Slave( parallel-syncs 參數).
    3. 等待舊 Master 復活,並使之稱爲新 Master 的 Slave.
    4. 向客戶端通知 Master 變化.
  • 從 Slave 中選擇新 Master 節點的規則(slave 升級成 master 之後)
    1. 選擇 slave-priority 最高的節點.
    2. 選擇複製偏移量最大的節點(同步數據最多).
    3. 選擇 runId 最小的節點.

讀寫分離

定時任務

  • 每 1s 每個 Sentinel 對其他 Sentinel 和 Redis 執行 ping,進行心跳檢測.
  • 每 2s 每個 Sentinel 通過 Master 的 Channel 交換信息(pub - sub).
  • 每 10s 每個 Sentinel 對 Master 和 Slave 執行 info,目的是發現 Slave 節點、確定主從關係.

分佈式集羣(Cluster)

拓撲圖

image

通訊

集中式

將集羣元數據(節點信息、故障等等)幾種存儲在某個節點上.

  • 優勢
    1. 元數據的更新讀取具有很強的時效性,元數據修改立即更新
  • 劣勢
    1. 數據集中存儲
Gossip

image

尋址分片

hash取模
  • hash(key)%機器數量
  • 問題
    1. 機器宕機,造成數據丟失,數據讀取失敗
    2. 伸縮性
一致性hash
  • image

  • 問題

    1. 一致性哈希算法在節點太少時,容易因爲節點分佈不均勻而造成緩存熱點的問題。
      • 解決方案
        • 可以通過引入虛擬節點機制解決:即對每一個節點計算多個 hash,每個計算結果位置都放置一個虛擬節點。這樣就實現了數據的均勻分佈,負載均衡。
hash槽
  • CRC16(key)%16384

image

使用場景

熱點數據

會話維持 session

分佈式鎖 SETNX

表緩存

消息隊列 list

計數器 string

緩存設計

更新策略

  • LRU、LFU、FIFO 算法自動清除:一致性最差,維護成本低.
  • 超時自動清除(key expire):一致性較差,維護成本低.
  • 主動更新:代碼層面控制生命週期,一致性最好,維護成本高.

更新一致性

  • 讀請求:先讀緩存,緩存沒有的話,就讀數據庫,然後取出數據後放入緩存,同時返回響應.
  • 寫請求:先刪除緩存,然後再更新數據庫(避免大量地寫、卻又不經常讀的數據導致緩存頻繁更新).

緩存粒度

  • 通用性:全量屬性更好.
  • 佔用空間:部分屬性更好.
  • 代碼維護成本.

緩存穿透

當大量的請求無命中緩存、直接請求到後端數據庫(業務代碼的 bug、或惡意攻擊),同時後端數據庫也沒有查詢到相應的記錄、無法添加緩存.
這種狀態會一直維持,流量一直打到存儲層上,無法利用緩存、還會給存儲層帶來巨大壓力.

解決方案

  1. 請求無法命中緩存、同時數據庫記錄爲空時在緩存添加該 key 的空對象(設置過期時間),缺點是可能會在緩存中添加大量的空值鍵(比如遭到惡意攻擊或爬蟲),而且緩存層和存儲層數據短期內不一致;
  2. 使用布隆過濾器在緩存層前攔截非法請求、自動爲空值添加黑名單(同時可能要爲誤判的記錄添加白名單).但需要考慮布隆過濾器的維護(離線生成/ 實時生成).

緩存雪崩

緩存崩潰時請求會直接落到數據庫上,很可能由於無法承受大量的併發請求而崩潰,此時如果只重啓數據庫,或因爲緩存重啓後沒有數據,新的流量進來很快又會把數據庫擊倒

出現後應對

  • 事前:Redis 高可用,主從 + 哨兵,Redis Cluster,避免全盤崩潰.
  • 事中:本地 ehcache 緩存 + hystrix 限流 & 降級,避免數據庫承受太多壓力.
  • 事後:Redis 持久化,一旦重啓,自動從磁盤上加載數據,快速恢復緩存數據.

請求過程

  1. 用戶請求先訪問本地緩存,無命中後再訪問 Redis,如果本地緩存和 Redis 都沒有再查數據庫,並把數據添加到本地緩存和 Redis;
  2. 由於設置了限流,一段時間範圍內超出的請求走降級處理(返回默認值,或給出友情提示).

事件型驅動

文件

時間

調度&執行

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