天天看點

分布式緩存:Redis1. Redis 原理、協定及使用;

本篇概要:

  • 1. Redis 原理、協定及使用;
    • 1.1 基本原理;
    • 1.2 資料類型;
    • 1.3 協定分析;
    • 1.4 Redis Client 的使用和改進;

1. Redis 原理、協定及使用;

1.1 基本原理;

Redis 簡介:

Redis 是一款基于 ANSI C 語言編寫的,BSD 許可的,日志型 key-value 存儲元件,它的所有資料結構都存在記憶體中,可以用作緩存、資料庫和消息中間件。

Redis 是 Remote dictionary server 即遠端字典服務的縮寫,一個 Redis 執行個體可以有多個存儲資料的字典,用戶端可以通過 select 來選擇字典即 DB 進行資料存儲。

Redis 特性:

同為 key-value 存儲元件,Memcached 隻能支援二進制位元組塊這一種資料類型。而 Redis 的資料類型卻豐富的多,它具有 8 種核心資料類型,每種資料類型都有一系列操作指令對應。Redis 性能很高,單線程壓測可以達到 10~11w 的 QPS。

雖然 Redis 所有資料的讀寫操作都在記憶體中進行,但也可以将所有資料進行落盤做持久化。Redis 提供了 2 種持久化方式。

  • 快照方式,将某時刻所有資料都寫入硬碟的 RDB 檔案;
  • 追加檔案方式,即将所有寫指令都以追加的方式寫入硬碟的 AOF 檔案中。

線上 Redis 一般會同時使用兩種方式,通過開啟 appendonly 及關聯配置項,将寫指令及時追加到 AOF 檔案,同時在每日流量低峰時,通過 bgsave 儲存當時所有記憶體資料快照。

對于網際網路系統的線上流量,讀操作遠遠大于寫操作。以微網誌為例,讀請求占總體流量的 90%左右。大量的讀請求,通常會遠超 Redis 的可承載範圍。此時,可以使用 Redis 的複制特性,讓一個 Redis 執行個體作為 master,然後通過複制挂載多個不斷同步更新的副本,即多個 slave。通過讀寫分離,把所有寫操作落在 Redis 的 master,所有讀操作随機落在 Redis 的多個 slave 中,進而大幅提升 Redis 的讀寫能力。

Lua 是一個高效、簡潔、易擴充的腳本語言,可以友善的嵌入其他語言中使用。Redis 自 2.6 版本開始支援 Lua。通過支援 client 端自定義的 Lua 腳本,Redis 可以減少網絡開銷,提升處理性能,還可以把腳本中的多個操作作為一個整體來操作,實作原子性更新。

Redis 還支援事務,在 multi 指令後,指定多個操作,然後通過 exec 指令一次性執行,中途如果出現異常,則不執行所有指令操作,否則,按順序一次性執行所有操作,執行過程中不會執行任何其他指令。

Redis 還支援 Cluster 特性,可以通過自動或手動方式,将所有 key 按哈希分散到不同節點,在容量不足時,還可以通過 Redis 的遷移指令,把其中一部分 key 遷移到其他節點。

分布式緩存:Redis1. Redis 原理、協定及使用;

Redis 的特性思維導圖

作為緩存元件,Redis 的最大優勢是支援豐富的資料類型。目前,Redis 支援 8 種核心資料類型,包括 string、list、set、sorted set、hash、bitmap、geo、hyperloglog。

Redis 的所有記憶體資料結構都存在全局的 dict 字典中,dict 類似 Memcached 的 hashtable。Redis 的 dict 也有 2 個哈希表,插入新 key 時,一般用 0 号哈希表,随着 key 的插入或删除,當 0 号哈希表的 keys 數大于哈希表桶數,或 keys 數小于哈希桶的 1/10 時,就對 hash 表進行擴縮。dict 中,哈希表解決沖突的方式,與 Memcached 相同,也是使用桶内單連結清單,來指向多個 hash 相同的 key / value 資料。

Redis 高性能

Redis 一般被看作單程序 / 單線程元件,因為 Redis 的網絡 IO 和指令處理,都在核心程序中由單線程處理。Redis 基于 Epoll 事件模型開發,可以進行非阻塞網絡 IO,同時由于單線程指令處理,整個處理過程不存在競争,不需要加鎖,沒有上下文切換開銷,所有資料操作都是在記憶體中操作,是以 Redis 的性能很高,單個執行個體即可以達到 10w 級的 QPS。核心線程除了負責網絡 IO 及指令處理外,還負責寫資料到緩沖,以友善将最新寫操作同步到 AOF、slave。

除了主程序,Redis 還會 fork 一個子程序,來進行重負荷任務的處理。Redis fork 子程序主要有 3 種場景。

  • 收到 bgrewriteaof 指令時,Redis 調用 fork,建構一個子程序,子程序往臨時 AOF檔案中,寫入重建資料庫狀态的所有指令,當寫入完畢,子程序則通知父程序,父程序把新增的寫操作也追加到臨時 AOF 檔案,然後将臨時檔案替換老的 AOF 檔案,并重命名。
  • 收到 bgsave 指令時,Redis 建構子程序,子程序将記憶體中的所有資料通過快照做一次持久化落地,寫入到 RDB 中。
  • 當需要進行全量複制時,master 也會啟動一個子程序,子程序将資料庫快照儲存到 RDB 檔案,在寫完 RDB 快照檔案後,master 就會把 RDB 發給 slave,同時将後續新的寫指令都同步給 slave。
    分布式緩存:Redis1. Redis 原理、協定及使用;
    主程序中,除了主線程處理網絡 IO 和指令操作外,還有 3 個輔助 BIO 線程。這 3 個 BIO 線程分别負責處理,檔案關閉、AOF 緩沖資料重新整理到磁盤,以及清理對象這三個任務隊列。

Redis 在啟動時,會同時啟動這三個 BIO 線程,然後 BIO 線程休眠等待任務。當需要執行相關類型的背景任務時,就會建構一個 bio_job 結構,記錄任務參數,然後将 bio_job 追加到任務隊列尾部。然後喚醒 BIO 線程,即可進行任務執行。

Redis 持久化

Redis 的持久化是通過 RDB 和 AOF 檔案進行的。RDB 隻記錄某個時間點的快照,可以通過設定指定時間内修改 keys 數的閥值,超過則自動建構 RDB 内容快照,不過線上運維,一般會選擇在業務低峰期定期進行。RDB 存儲的是建構時刻的資料快照,記憶體資料一旦落地,不會理會後續的變更。而 AOF,記錄是建構整個資料庫内容的指令,它會随着新的寫操作不斷進行追加操作。由于不斷追加,AOF 會記錄資料大量的中間狀态,AOF 檔案會變得非常大,此時,可以通過 bgrewriteaof 指令,對 AOF 進行重寫,隻保留資料的最後内容,來大大縮減 AOF 的内容。

分布式緩存:Redis1. Redis 原理、協定及使用;

為了提升系統的可擴充性,提升讀操作的支撐能力,Redis 支援 master-slave 的複制功能。當 Redis 的 slave 部署并設定完畢後,slave 會和 master 建立連接配接,進行全量同步。

第一次建立連接配接,或者長時間斷開連接配接後,缺失的指令超過 master 複制緩沖區的大小,都需要先進行一次全量同步。全量同步時,master 會啟動一個子程序,将資料庫快照儲存到檔案中,然後将這個快照檔案發給 slave,同時将快照之後的寫指令也同步給 slave。

全量同步完成後,如果 slave 短時間中斷,然後重連複制,缺少的寫指令長度小于 master 的複制緩沖大小,master 就會把 slave 缺失的内容全部發送給 slave,進行增量複制。

Redis 的 master 可以挂載多個 slave,同時 slave 還可以繼續挂載 slave,通過這種方式,可以有效減輕 master 的壓力,同時在 master 挂掉後,可以在 slave 通過 slaveof no one 指令,使目前 slave 停止與 master 的同步,轉而成為新的 master。

Redis 叢集管理

Redis 的叢集管理有 3 種方式。

  • client 分片通路,client 對 key 做 hash,然後按取模或一緻性 hash,把 key 的讀寫分散到不同的 Redis 執行個體上。
  • 在 Redis 前加一個 proxy,把路由政策、後端 Redis 狀态維護的工作都放到 proxy 中進行,client 直接通路 proxy,後端 Redis 變更,隻需修改 proxy 配置即可。
  • 直接使用 Redis cluster。Redis 建立之初,使用方直接給 Redis 的節點配置設定 slot,後續通路時,對 key 做 hash 找到對應的 slot,然後通路 slot 所在的 Redis 執行個體。在需要擴容縮容時,可以線上通過 cluster setslot 指令,以及 migrate 指令,将 slot 下所有 key 遷移到目标節點,即可實作擴縮容的目的。

1.2 資料類型;

Redis 有 8 種核心資料類型:

  • string 字元串類型;
  • list 清單類型;
  • set 集合類型;
  • sorted set 有序集合類型;
  • hash 類型;
  • bitmap 位圖類型;
  • geo 地理位置類型;
  • HyperLogLog 基數統計類型。

string 字元串

string 是 Redis 的最基本資料類型。可以把它了解為 Mc 中 key 對應的 value 類型。string 類型是二進制安全的,即 string 中可以包含任何資料。

Redis 中的普通 string 采用 raw encoding 即原始編碼方式,該編碼方式會動态擴容,并通過提前預配置設定備援空間,來減少記憶體頻繁配置設定的開銷。

在字元串長度小于 1MB 時,按所需長度的 2 倍來配置設定,超過 1MB,則按照每次額外增加 1MB 的容量來預配置設定。

Redis 中的數字也存為 string 類型,但編碼方式跟普通 string 不同,數字采用整型編碼,字元串内容直接設為整數值的二進制位元組序列。

在存儲普通字元串,序列化對象,以及計數器等場景時,都可以使用 Redis 的字元串類型,字元串資料類型對應使用的指令包括 set、get、mset、incr、decr 等。

list 清單

Redis 的 list 清單,是一個快速雙向連結清單,存儲了一系列的 string 類型的字串值。list 中的元素按照插入順序排列。插入元素的方式,可以通過 lpush 将一個或多個元素插入到清單的頭部,也可以通過 rpush 将一個或多個元素插入到隊列尾部,還可以通過 lset、linsert 将元素插入到指定位置或指定元素的前後。

list 清單的擷取,可以通過 lpop、rpop 從對頭或隊尾彈出元素,如果隊列為空,則傳回 nil。還可以通過 Blpop、Brpop 從隊頭 / 隊尾阻塞式彈出元素,如果 list 清單為空,沒有元素可供彈出,則持續阻塞,直到有其他 client 插入新的元素。這裡阻塞彈出元素,可以設定過期時間,避免無限期等待。最後,list 清單還可以通過 LrangeR 擷取隊列内指定範圍内的所有元素。Redis 中,list 清單的偏移位置都是基于 0 的下标,即清單第一個元素的下标是 0,第二個是 1。偏移量也可以是負數,倒數第一個是 -1,倒數第二個是 -2,依次類推。

分布式緩存:Redis1. Redis 原理、協定及使用;

list 清單,對于正常的 pop、push 元素,性能很高,時間複雜度為 O(1),因為是清單直接追加或彈出。但對于通過随機插入、随機删除,以及随機範圍擷取,需要輪詢清單确定位置,性能就比較低下了。

feed timeline 存儲時,由于 feed id 一般是遞增的,可以直接存為 list,使用者發表新 feed,就直接追加到隊尾。另外消息隊列、熱門 feed 等業務場景,都可以使用 list 資料結構。

操作 list 清單時,可以用 lpush、lpop、rpush、rpop、lrange 來進行正常的隊列進出及範圍擷取操作,在某些特殊場景下,也可以用 lset、linsert 進行随機插入操作,用 lrem 進行指定元素删除操作;最後,在消息清單的消費時,還可以用 Blpop、Brpop 進行阻塞式擷取,進而在清單暫時沒有元素時,可以安靜的等待新元素的插入,而不需要額外持續的查詢。

set 集合

set 是 string 類型的無序集合,set 中的元素是唯一的,即 set 中不會出現重複的元素。Redis 中的集合一般是通過 dict 哈希表實作的,是以插入、删除,以及查詢元素,可以根據元素 hash 值直接定位,時間複雜度為 O(1)。

對 set 類型資料的操作,除了正常的添加、删除、查找元素外,還可以用以下指令對 set 進行操作。

  • sismember 指令判斷該 key 對應的 set 資料結構中,是否存在某個元素,如果存在傳回 1,否則傳回 0;
  • sdiff 指令來對多個 set 集合執行差集;
  • sinter 指令對多個集合執行交集;
  • sunion 指令對多個集合執行并集;
  • spop 指令彈出一個随機元素;
  • srandmember 指令傳回一個或多個随機元素。

set 集合的特點是查找、插入、删除特别高效,時間複雜度為 O(1),是以在社交系統中,可以用于存儲關注的好友清單,用來判斷是否關注,還可以用來做好友推薦使用。比如,某使用者關注了 A、B、C、D 這四個使用者,這四個使用者也同時關注了 E、F,那麼 E、F 也很大機率被該使用者感興趣,可以向該使用者推薦。另外,還可以利用 set 的唯一性,來對服務的來源業務、來源 IP 進行精确統計。

sorted set 有序集合

Redis 中的 sorted set 有序集合也稱為 zset,有序集合同 set 集合類似,也是 string 類型元素的集合,且所有元素不允許重複。

但有序集合中,每個元素都會關聯一個 double 類型的 score 分數值。有序集合通過這個 score 值進行由小到大的排序。有序集合中,元素不允許重複,但 score 分數值卻允許重複。

有序集合除了正常的添加、删除、查找元素外,還可以通過以下指令對 sorted set 進行操作。

  • zscan 指令:按順序擷取有序集合中的元素;
  • zscore 指令:擷取元素的 score 值;
  • zrange指令:通過指定 score 傳回擷取 scpre 範圍内的元素;
  • 在某個元素的 score 值發生變更時,還可以通過 zincrby 指令對該元素的 score 值進行加減。
  • 通過 zinterstore、zunionstore 指令對多個有序集合進行取交集和并集,然後将新的有序集合存到一個新的 key 中,如果有重複元素,重複元素的 score 進行相加,然後作為新集合中該元素的 score 值。

sorted set 有序集合的特點是:

  • 所有元素按 score 排序,而且不重複;
  • 查找、插入、删除非常高效,時間複雜度為 O(1)。

是以,可以用有序集合來統計排行榜,實時重新整理榜單,還可以用來記錄學生成績,進而輕松擷取某個成績範圍内的學生名單,還可以用來對系統統計增權重重值,進而在 dashboard 實時展示。

hash 哈希

Redis 中的哈希實際是 field 和 value 的一個映射表。

hash 資料結構的特點是在單個 key 對應的哈希結構内部,可以記錄多個鍵值對,即 field 和 value 對,value 可以是任何字元串。而且這些鍵值對查詢和修改很高效。

是以可以用 hash 來存儲具有多個元素的複雜對象,然後分别修改或擷取這些元素。hash 結構中的一些重要指令,包括:hmset、hmget、hexists、hgetall、hincrby 等。

  • hmset 指令批量插入多個 field、value 映射;
  • hmget 指令擷取多個 field 對應的 value 值;
  • hexists 指令判斷某個 field 是否存在;
  • 如果 field 對應的 value 是整數,還可以用 hincrby 來對該 value 進行修改。

bitmap 位圖

Redis 中的 bitmap 位圖是一串連續的二進制數字,底層實際是基于 string 進行封裝存儲的,按 bit 位進行指令操作的。bitmap 中每一 bit 位所在的位置就是 offset 偏移,可以用 setbit、bitfield 對 bitmap 中每個 bit 進行置 0 或置 1 操作,也可以用 bitcount 來統計 bitmap 中的被置 1 的 bit 數,還可以用 bitop 來對多個 bitmap 進行求與、或、異或等操作。

分布式緩存:Redis1. Redis 原理、協定及使用;

bitmap 位圖的特點是按位設定、求與、求或等操作很高效,而且存儲成本非常低,用來存對象标簽屬性的話,一個 bit 即可存一個标簽。可以用 bitmap,存使用者最近 N 天的登入情況,每天用 1 bit,登入則置 1。個性推薦在社交應用中非常重要,可以對新聞、feed 設定一系列标簽,如軍事、娛樂、視訊、圖檔、文字等,用 bitmap 來存儲這些标簽,在對應标簽 bit 位上置 1。對使用者,也可以采用類似方式,記錄使用者的多種屬性,并可以很友善的根據标簽來進行多元度統計。bitmap 位圖的重要指令包括:setbit、 getbit、bitcount、bitfield、 bitop、bitpos 等。

在移動社交時代,LBS 應用越來越多,比如微信、陌陌中附近的人,美團、大衆點評中附近的美食、電影院,滴滴、優步中附近的專車等。要實作這些功能,就得使用地理位置資訊進行搜尋。地球的地理位置是使用二維的經緯度進行表示的,我們隻要确定一個點的經緯度,就可以确認它在地球的位置。

Redis 在 3.2 版本之後增加了對 GEO 地理位置的處理功能。Redis 的 GEO 地理位置本質上是基于 sorted set 封裝實作的。在存儲分類 key 下的地理位置資訊時,需要對該分類 key 建構一個 sorted set 作為内部存儲結構,用于存儲一系列位置點。

在存儲某個位置點時,首先利用 Geohash 算法,将該位置二維的經緯度,映射編碼成一維的 52 位整數值,将位置名稱、經緯度編碼 score 作為鍵值對,存儲到分類 key 對應的 sorted set 中。

需要計算某個位置點 A 附近的人時,首先以指定位置 A 為中心點,以距離作為半徑,算出 GEO 哈希 8 個方位的範圍, 然後依次輪詢方位範圍内的所有位置點,隻要這些位置點到中心位置 A 的距離在要求距離範圍内,就是目标位置點。輪詢完所有範圍内的位置點後,重新排序即得到位置點 A 附近的所有目标。

  • 使用 geoadd,将位置名稱(如人、車輛、店名)與對應的地理位置資訊添加到指定的位置分類 key 中;
  • 使用 geopos 友善地查詢某個名稱所在的位置資訊;
  • 使用 georadius 擷取指定位置附近,不超過指定距離的所有元素;
  • 使用 geodist 來擷取指定的兩個位置之間的距離。

這樣,是不是就可以實作,找到附近的餐廳,算出目前位置到對應餐廳的距離,這樣的功能了?

Redis GEO 地理位置,利用 Geohash 将大量的二維經緯度轉一維的整數值,這樣可以友善的對地理位置進行查詢、距離測量、範圍搜尋。但由于地理位置點非常多,一個地理分類 key 下可能會有大量元素,在 GEO 設計時,需要提前進行規劃,避免單 key 過度膨脹。

Redis 的 GEO 地理位置資料結構,應用場景很多,比如查詢某個地方的具體位置,查目前位置到目的地的距離,查附近的人、餐廳、電影院等。GEO 地理位置資料結構中,重要指令包括 geoadd、geopos、geodist、georadius、georadiusbymember 等。

hyperLogLog 基數統計

Redis 的 hyperLogLog 是用來做基數統計的資料類型,當輸入巨大數量的元素做統計時,隻需要很小的記憶體即可完成。HyperLogLog 不儲存中繼資料,隻記錄待統計元素的估算數量,這個估算數量是一個帶有 0.81% 标準差的近似值,在大多數業務場景,對海量資料,不足 1% 的誤差是可以接受的。

Redis 的 HyperLogLog 在統計時,如果計數數量不大,采用稀疏矩陣存儲,随着計數的增加,稀疏矩陣占用的空間也會逐漸增加,當超過閥值後,則改為稠密矩陣,稠密矩陣占用的空間是固定的,約為12KB位元組。

通過 hyperLoglog 資料類型,你可以利用 pfadd 向基數統計中增加新的元素,可以用 pfcount 獲得 hyperLogLog 結構中存儲的近似基數數量,還可以用 hypermerge 将多個 hyperLogLog 合并為一個 hyperLogLog 結構,進而可以友善的擷取合并後的基數數量。

hyperLogLog 的特點是統計過程不記錄獨立元素,占用記憶體非常少,非常适合統計海量資料。在大中型系統中,統計每日、每月的 UV 即獨立訪客數,或者統計海量使用者搜尋的獨立詞條數,都可以用 hyperLogLog 資料類型來進行處理。

1.3 協定分析;

Redis 支援 8 種核心資料結構,每種資料結構都有一系列的操作指令,除此之外,Redis 還有事務、叢集、釋出訂閱、腳本等一系列相關的指令。為了友善以一種統一的風格和原則來設計和使用這些指令,Redis 設計了 RESP,即 Redis Serialization Protocol,中文意思是 Redis 序列化協定。RESP 是二進制安全協定,可以供 Redis 或其他任何 Client-Server 使用。在 Redis 内部,還會基于 RESP 進一步擴充細節。

設計原則

Redis 序列化協定的設計原則有三個:

  • 第一是實作簡單
  • 第二是可快速解析
  • 第三是便于閱讀

Redis 協定的請求響應模型有三種,除了 2 種特殊模式,其他基本都是 ping-pong 模式,即 client 發送一個請求,server 回複一個響應,一問一答的通路模式。

2 種特殊模式:

  • pipeline 模式,即 client 一次連續發送多個請求,然後等待 server 響應,server 處理完請求後,把響應傳回給 client。
  • pub/sub 模式。即釋出訂閱模式,client 通過 subscribe 訂閱一個 channel,然後 client 進入訂閱狀态,靜靜等待。當有消息産生時,server 會持續自動推送消息給 client,不需要 client 的額外請求。而且用戶端在進入訂閱狀态後,隻可接受訂閱相關的指令如 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE 和 PUNSUBSCRIBE,除了這些指令,其他指令一律失效。

Redis 協定的請求和響應也是有固定套路的。

  • 對于請求指令,格式有 2 種類型。
  • 當你沒有 redis-client,但希望可以用通用工具 telnet,直接與 Redis 互動時,Redis 協定雖然簡單易于閱讀,但在互動式會話中使用,并不容易拼寫,此時可以用第一種格式,即 inline cmd 内聯指令格式。使用 inline cmd 内聯格式,隻需要用空格分隔請求指令及參數,簡單快速,一個簡單的例子如 mget key1 key2\r\n。

第二種格式是 Array 數組格式類型。請求指令用的數組類型,與 Redis 響應的數組類型相同。

響應格式

Redis 協定的響應格式有 5 種,分别是:

  • simple strings 簡單字元串類型,以 + 開頭,後面跟字元串,以 CRLF(即 \r\n)結尾。這種類型不是二進制安全類型,字元串中不能包含 \r 或者 \n。比如許多響應回複以 OK 作為操作成功的标志,協定内容就是 +OK\r\rn 。
  • Redis 協定将錯誤作為一種專門的類型,格式同簡單字元串類型,唯一不同的是以 -(減号)開頭。Redis 内部實作對 Redis 協定做了進一步規範,減号後面一般先跟 ERR 或者 WRONGTYPE,然後再跟其他簡單字元串,最後以 CRLF(回車換行)結束。這裡給了兩個示例,client 在解析響應時,一旦發現 - 開頭,就知道收到 Error 響應。
  • Integer 整數類型。整數類型以 :開頭,後面跟字元串表示的數字,最後以回車換行結尾。Redis 中許多指令都傳回整數,但整數的含義要由具體指令來确定。比如,對于 incr 指令,:後的整數表示變更後的數值;對于 llen 表示 list 清單的長度,對于 exists 指令,1 表示 key 存在,0 表示 key 不存在。這裡給個例子,:後面跟了個 1000,然後回車換行結束。
  • bulk strings 字元串塊類型。字元串塊分頭部和真正字元串内容兩部分。字元串塊類型的頭部, 為 $ 開頭,随後跟真正字元串内容的位元組長度,然後以 CRLF 結尾。字元串塊的頭部之後,跟随真正的字元串内容,最後以 CRLF 結束字元串塊。字元串塊用于表示二進制安全的字元串,最大長度可以支援 512MB。一個正常的例子,“

    $6\r\nfoobar\r\n

    ”,對于空字串,可以表示為 “

    $0\r\n\r\n

    ”,NULL字串: “

    $-1\r\n

    ”。
  • Arrays 數組類型,如果一個指令需要傳回多條資料就需要用數組格式類型,另外,前面提到 client 的請求指令也是主要采用這種格式。

Arrays 數組類型,以 * 開頭,随後跟一個數組長度 N,然後以回車換行結尾;然後後面跟随 N 個數組元素,每個數組元素的類型,可以是 Redis 協定中除内聯格式外的任何一種類型。

比如一個字元串塊的數組執行個體,

*2\r\n$3\r\nget\r\n$3\r\nkey\r\n

。整數數組執行個體:

"*3\r\n:1\r\n:2\r\n:3\r\n"

,混合數組執行個體:

"*3\r\n :1\r\n-Bar\r\n$6\r\n foobar\r\n"

,空數組:

"*0\r\n"

,NULL數組:

"*-1\r\n"

協定分類

Redis 協定主要分為 16 種,其中 8 種協定對應前面我們講到的 8 種資料類型,你選擇了使用什麼資料類型,就使用對應的響應操作指令即可。剩下 8 種協定如下所示。

  • pub-sub 釋出訂閱協定,client 可以訂閱 channel,持續等待 server 推送消息。
  • 事務協定,事務協定可以用 multi 和 exec 封裝一些列指令,來一次性執行。
  • 腳本協定,關鍵指令是 eval、evalsha 和 script等。
  • 連接配接協定,主要包括權限控制,切換 DB,關閉連接配接等。
  • 複制協定,包括 slaveof、role、psync 等。
  • 配置協定,config set/get 等,可以線上修改/擷取配置。
  • 調試統計協定,如 slowlog,monitor,info 等。
  • 其他内部指令,如 migrate,dump,restore 等。

1.4 Redis Client 的使用和改進;

由于 Redis 使用廣泛,幾乎所有主流語言都有對 Redis 開發了對應的 client。以 Java 語言為例,廣泛使用的有 Jedis、Redisson 等。對于 Jedis client,它的優勢是輕量,簡潔,便于內建和改造,它支援連接配接池,提供指令次元的操作,幾乎支援 Redis 的所有指令,但它不支援讀寫分離。Redisson 基于 Netty 實作,非阻塞 IO,性能較高,而且支援異步請求和連接配接池,還支援讀寫分離、讀負載均衡,它内建了 tomcat Session ,支援 spring session 內建,但 redisson 實作相對複雜。

在新項目啟動時,如果隻是簡單的 Redis 通路業務場景,可以直接用 Jedis,甚至可以簡單封裝 Jedis,實作 master-slave 的讀寫分離方案。如果想直接使用讀寫分離,想內建 spring session 等這些進階特性,也可以采用 redisson。

Redis client 在使用中,需要根據業務及運維的需要,進行相關改進。在 client 通路異常時,可以增加重試政策,在通路某個 slave 異常時,需要重試其他 slave 節點。需要增加對 Redis 主從切換、slave 擴充的支援,比如采用守護線程定期掃描 master、slave 域名,發現 IP 變更,及時切換連接配接。對于多個 slave 的通路,還需要增加負載均衡政策。最後,Redis client 還可以與配置中心、Redis 叢集管理平台整合,進而實時感覺及協調 Redis 服務的通路。

分布式緩存:Redis1. Redis 原理、協定及使用;

繼續閱讀