- Redis有哪些數據類型?底層實現分別是什么
Redis數據類型概述
Redis作為一款鍵值存儲系統,提供了豐富多樣的數據類型以滿足不同場景的需求。以下是Redis支持的主要數據類型及其基本用途:
String(字符串)
存儲單個鍵值對,支持增刪改查、自增、截取等操作。
應用場景:計數器、緩存、分布式鎖等。
底層實現:Redis字符串是動態字符串(SDS),其內部結構包含長度、已用長度和字節數組。
編碼方式:Redis對字符串值的存儲采用多種編碼,如:
REDIS_ENCODING_INT:當值為整數且在一定范圍內時,直接存儲整數值,節省空間。
REDIS_ENCODING_EMBSTR:對于短字符串,使用embstr編碼,將字符串與結構體緊湊存儲在同一塊連續內存中,減少內存分配次數。
REDIS_ENCODING_RAW:長字符串或非整數值使用raw編碼,即傳統的簡單動態字符串。
List(列表)
有序的字符串列表,支持兩端插入、彈出、范圍查詢等操作。
應用場景:消息隊列、最新N個元素列表等。
底層實現:列表有兩種編碼方式,分別是:
ziplist(壓縮列表):對于元素數量少且元素長度較短的列表,使用連續內存存儲,節省空間。
linkedlist(雙端鏈表):當列表元素數量或長度超過一定閾值時,轉為雙端鏈表實現,保證操作的高效性。
Set(集合)
無序的字符串集合,不允許重復成員,支持添加、刪除、成員關系判斷等操作。
應用場景:標簽系統、唯一性檢查、交并差集運算等。
底層實現:集合也有兩種編碼:
intset(整數集合):當集合中所有元素都是整數且范圍適當時,使用整數集合存儲,空間效率高。
hashtable(哈希表):當集合包含非整數元素或元素數量超過一定閾值時,轉化為哈希表實現,提供快速的增刪查操作。
Sorted Set(有序集合)
類似集合,但每個成員附帶一個分數,依據分數進行排序。
支持添加、刪除、按分數范圍查詢、排名、聚合操作等。
應用場景:排行榜、帶權重的標簽系統、Top N查詢等。
底層實現:有序集合基于ziplist或skiplist(跳躍表)編碼:
ziplist:小型有序集合,使用壓縮列表存儲,元素按分數排序。
skiplist:大型有序集合,使用跳躍表實現,提供O(log N)的插入、刪除、查找等操作,同時保留了集合成員的順序。
Hash(哈希)
鍵值對的集合,每個鍵值對由field-value組成。
支持增刪改查單個field,批量操作整個哈希。
應用場景:對象屬性存儲、購物車等。
底層實現:哈希同樣存在兩種編碼:
ziplist:對于小規模哈希(字段數量和值長度較小),使用壓縮列表存儲,緊湊且高效。
hashtable:當哈希的字段數量或值長度超過閾值時,轉化為哈希表實現,提供快速的字段查找和更新。
Bitmaps(位圖)
功能:Bitmaps允許以位(bit)為單位存儲數據,非常適合用來表示稀疏的二進制狀態,如用戶簽到、統計用戶行為等。
應用案例:用戶簽到系統
假設有一個網站需要記錄用戶每天的簽到情況。對于每個用戶,我們可以使用一個唯一的用戶ID作為鍵名,用Bitmaps來表示其連續365天的簽到狀態。每天簽到時,使用SETBIT命令將對應日期的位設置為1。查詢用戶在過去一周是否有連續簽到,則可通過BITCOUNT命令計算過去7天的位圖中值為1的位數。
底層實現:在Redis中,位圖實際上是基于字符串(String)類型實現的,每個字節(8位)對應字符串中的一個字符。通過對字符串執行位操作命令(如SETBIT,?GETBIT,?BITCOUNT,?BITOP等),可以高效地進行位的增刪查改。
HyperLogLog
功能:HyperLogLog是一種概率數據結構,用于估算集合中不重復元素(基數)的大致數量,而不需要存儲所有元素。它以極小的空間開銷(通常幾百字節)提供接近精確的計數,適用于大規模唯一計數場景,如網站獨立訪客統計、唯一事件計數等。
應用案例:網站獨立訪客統計
在一個網站中,需要統計每天訪問的獨立訪客數,但不想為每個訪客保存完整的訪問記錄。可以為每天創建一個HyperLogLog鍵,每當有新的訪客訪問時,將其唯一標識符(如IP地址或用戶代理字符串的哈希值)添加到當天的HyperLogLog中。使用PFADD命令添加元素,PFCOUNT命令獲取估計的獨立訪客數。
底層實現:HyperLogLog使用特定的哈希函數和概率算法估計基數,不直接存儲元素,而是維護一個內部狀態來近似計數。
Geospatial Indexes(地理位置索引)
功能:Redis提供了對地理位置數據的支持,可以存儲經緯度坐標,并進行距離查詢、范圍查詢(如“附近的人”功能)、地理圍欄(如“在某區域內的人”)等操作。
應用案例:“附近的人”功能
在社交應用中,用戶可以查看當前位置附近的其他在線用戶。為每個用戶存儲其經緯度坐標,使用GEOADD命令將用戶位置添加到地理位置索引中。當查詢時,使用GEORADIUS或GEORADIUSBYMEMBER命令查找指定半徑內的其他用戶。
底層實現:使用有序集合(Sorted Set)存儲地理位置數據,成員為地理位置的標識符,分值為經過特定公式轉換后的經緯度坐標,以此實現空間索引。
Streams(流)
功能:Redis Streams是一種用于存儲和處理時間序列數據的數據結構,特別適用于構建消息隊列、活動日志、審計跟蹤等應用場景。它支持多消費者消費同一數據流的不同部分,并具備消息持久化、消息ID生成、消息分片(Consumer Group)等功能。
應用案例:訂單事件日志
在電商系統中,使用Redis Stream記錄訂單相關的事件,如訂單創建、支付成功、發貨等。每個事件作為一個消息,包含事件類型、發生時間、訂單ID等信息。消費者(如后臺任務、實時分析服務)通過XREAD或XREADGROUP命令訂閱并處理這些事件。
底層實現:Stream數據結構在內部以鍵值對的形式存儲,鍵為Stream的名字,值為一個特殊的字典結構,包含多個消息列表(每個消息列表代表一個分片)以及相關元數據。
如果大家需要視頻版本的講解,歡迎關注我的B站: