一文徹底搞透Redis的資料型別及具體的應用場景

lgx211發表於2024-10-24

Redis 提供了豐富的資料型別,每種資料型別都有其獨特的儲存結構和操作方法,可以滿足不同的業務場景需求。下面詳細介紹 Redis 支援的主要資料型別及其底層實現,並結合具體的應用場景說明其使用。

1. 字串(String)

介紹:

  • Redis 中最基本的鍵值對型別,鍵和值都可以是字串,值的最大限制為 512MB。
  • String 型別是 Redis 最常用的資料型別,它支援簡單的 GETSET 操作,以及自增、自減、字串拼接等操作。

典型應用場景:

  • 快取資料:儲存使用者登入狀態、Token、配置資訊等。
  • 計數器:透過 INCRDECR 實現簡單的計數器,比如網站訪問量、點贊數等。
  • 分散式鎖:結合 SETNX 命令,可以用字串來實現簡單的分散式鎖。

底層原理:

  • Redis 底層對字串使用的是簡單動態字串(SDS),它不僅是 C 字串的封裝,還加入了長度屬性和空間預留等最佳化策略。SDS 支援二進位制安全,可以儲存文字和二進位制資料。

2. 雜湊(Hash)

介紹:

  • 雜湊是一個鍵值對集合,適合儲存物件。每個鍵可以有多個欄位,每個欄位都有一個值。
  • 操作包括 HSETHGETHDEL 等。

典型應用場景:

  • 儲存使用者資訊:如使用者 ID 作為鍵,使用者的屬性(姓名、年齡、性別等)作為欄位,避免將整個使用者物件序列化成字串。
  • 配置項管理:儲存配置項,方便根據欄位名快速訪問和更新某個配置。

底層原理:

  • 雜湊使用了兩種底層資料結構:小資料量時使用壓縮列表(ziplist),大資料量時使用雜湊表(hashtable)。壓縮列表可以節省記憶體,但隨著雜湊表的增長會自動轉換為雜湊表,保證查詢效率。

3. 列表(List)

介紹:

  • 列表是一個雙向連結串列,可以從頭部或尾部插入、刪除元素,常用命令包括 LPUSHRPUSHLPOPRPOP 等。
  • Redis 支援阻塞操作,如 BLPOPBRPOP,在沒有元素時可以阻塞等待。

典型應用場景:

  • 訊息佇列:列表可以作為簡單的訊息佇列,用 LPUSH 將訊息放入佇列,用 RPOPBRPOP 彈出訊息。
  • 任務排程:非同步任務分發系統中,可以將任務放入佇列中,由多個消費者去消費。

底層原理:

  • 列表採用雙向連結串列(quicklist)實現。對於較短的列表,Redis 會使用壓縮列表(ziplist)來節省記憶體;對於較長的列表,則會採用真正的雙向連結串列來平衡操作的時間複雜度。

4. 集合(Set)

介紹:

  • 集合是無序的、唯一的元素集合,提供類似於數學集合的操作,支援交集、並集、差集等。
  • 常用操作包括 SADDSREMSISMEMBERSMEMBERSSINTER 等。

典型應用場景:

  • 標籤系統:如將使用者標籤儲存為集合,每個集合代表一個使用者群體,方便進行集合運算,如找出同時擁有某兩個標籤的使用者。
  • 去重功能:在某些場景下(如熱門搜尋詞、訪問日誌的去重),可以透過集合的唯一性特性來避免重複資料。

底層原理:

  • 小集合時使用整數集合(intset),大集合時使用雜湊表(hashtable)實現。透過雜湊表的快速查詢特性,可以實現 O(1) 的時間複雜度來判斷元素是否存在。

5. 有序集合(Sorted Set)

介紹:

  • 有序集合類似於集合,但每個元素關聯一個分數,集合中的元素會按分數排序。支援的操作包括 ZADDZRANGEZREMZREVRANGEZCOUNT 等。

典型應用場景:

  • 排行榜:比如遊戲中的積分榜,按使用者分數進行排名。可以透過 ZADD 新增玩家及其分數,透過 ZRANGE 獲取排名。
  • 延遲任務:透過分數設定任務執行的時間,按時間從集合中取出需要執行的任務。

底層原理:

  • 有序集合底層使用的是跳錶(Skiplist)和雜湊表相結合的資料結構,跳錶使得有序集合支援快速的範圍查詢和插入操作(時間複雜度 O(logN)),而雜湊表保證元素的快速定位。

6. 點陣圖(Bitmaps)

介紹:

  • 點陣圖實際上是字串型別的擴充套件,可以把字串看作一系列連續的二進位制位,可以對這些二進位制位進行位操作。支援的命令有 SETBITGETBITBITCOUNTBITOP 等。

典型應用場景:

  • 使用者簽到系統:用點陣圖儲存使用者的簽到記錄,每天對應一個 bit,0 表示未簽到,1 表示已簽到。
  • 活躍使用者統計:透過點陣圖儲存某一時間段內使用者是否活躍,快速統計某天有多少活躍使用者。

底層原理:

  • 點陣圖的底層儲存是 Redis 的字串結構,但位操作是直接針對每個二進位制位,因此能夠在非常緊湊的儲存空間內實現高效的操作,適合海量資料場景。

7. HyperLogLog

介紹:

  • HyperLogLog 是一種用於基數統計的演算法,可以用於估算一個集合中不重複元素的個數,且佔用的記憶體空間非常小。
  • 常用命令有 PFADDPFCOUNT

典型應用場景:

  • 獨立訪客統計:在網站分析中統計獨立訪客(UV),只需為每個訪客 ID 新增到 HyperLogLog 中,快速得到不重複使用者數。
  • 大規模資料去重計數:用於估算大規模資料中的去重個數,如點選、請求、訪問量等。

底層原理:

  • HyperLogLog 是一種基數估計演算法,透過雜湊分佈將資料對映到位向量中,透過統計不同字首的最大長度來估算基數,其優點是佔用記憶體極小,缺點是隻能進行估算,存在一定誤差。

8. 地理空間(Geospatial)

介紹:

  • Redis 支援儲存地理位置資料,並基於這些資料進行範圍查詢和距離計算。常用命令包括 GEOADDGEODISTGEORADIUSGEOHASH 等。

典型應用場景:

  • LBS 應用:比如叫車應用中,儲存司機和乘客的地理位置,根據位置計算距離,匹配最近的車輛。
  • 附近商家搜尋:使用者輸入位置後,查詢附近的商家,並根據距離排序返回。

底層原理:

  • Redis 的地理空間資料是基於有序集合實現的,使用 GEOHASH 演算法將地理座標編碼為 64 位的整數,存入有序集合中。透過對這些編碼的範圍查詢,可以實現快速的空間檢索。

9. 流(Streams)

介紹:

  • Stream 是 Redis 5.0 引入的一種新的資料型別,支援訊息佇列的功能,類似於 Kafka 或者 RabbitMQ,支援消費組、訊息持久化和自動應答等特性。常用命令包括 XADDXREADXGROUPXACK 等。

典型應用場景:

  • 訊息系統:透過流資料型別,多個消費者可以從同一個佇列中消費資料,實現訊息分發和處理。
  • 日誌系統:可以將日誌資訊儲存在 Redis 的流中,實現持久化和實時消費。

底層原理:

  • Stream 是基於壓縮列表和連結串列的結合體,資料結構複雜度較高,可以高效儲存大量的流式資料。透過內部維護的 ID 進行排序和管理,使得它適合處理有序的、持續生成的資料流。

總結

Redis 提供的多種資料型別,不僅豐富了其在不同業務場景下的適用性,還能透過記憶體友好的資料結構和高效的演算法來保證效能。在選擇 Redis 資料型別時,通常需要根據業務需求來匹配合適的資料結構,從而最大限度地提升系統效能和資源利用率。

相關文章