「Redis」BitMap 再絮叨

不積跬步,無以至千里;不積小流,無以成江海。

之前寫過一篇關於 BitMap 的文章,寫的並不通透,在大數據下 BitMap 優勢還是顯而易見的,所以決定重寫,面試的時候你能掌握以下絕對是你的加分項。

在我們平時開發過程中,難免會有一些 bool 型 數據需要存取

比如以下場景:

某個用戶是否點贊過某篇文章某個用戶今天是否登陸過某個用戶的簽到情況統計產品的月活
什麼是 BitMap

位圖 並不是特殊的數據結構,它的內容其實就是普通的字符串,也就是 byte數組,用二進制表示,只有 0 和 1

我們可以使用普通的 get/set 直接獲取和設置 整個位圖 的內容也可以使用位圖操作 getbit/setbit 等將 byte 數組 看成「位數組」來處理。

如下:


用法


居然不支持 MarkDown, 只有截圖上來了。

優勢
基於最小的單位 bit 進行存儲,節省空間。set 時間複雜度 O(1)、get 時間複雜度 O(n),操作是非常快的。二進制數據的存儲,進行相關計算的時候非常快。自動擴容,如果設置了某個偏移位置超出了現有的內容範圍,就會 自動 將位數組進行零擴充。
弊端
redis中bit映射被限制在512MB之內,所以最大是2^32位,再大時需要分片存取。建議每個key的位數都進行控制,因為讀取時候時間複雜度O(n),越大的串讀的時間花銷越多。offset 稀疏時不建議用,浪費大量內存
空間、時間粗略計算方式

在一臺 2010MacBook Pro上,offset 為 2^32-1(分配512MB)需要~300ms,


offset為2^30-1(分配128MB)需要~80ms,


offset為2^28-1(分配32MB)需要~30ms,


offset為2^26-1(分配8MB)需要8ms。

大概的空間佔用計算公式是:($offset/8/1024/1024)MB

使用場景
用戶簽到

記錄用戶每天簽到情況,同時能快速知道用戶某天是否簽到

偽代碼:



活躍用戶

統計某段時間內的活躍用戶 只需要一個key,然後用戶id為偏移量offset,如果登陸過就設置為1,反之就設置為0,

偽代碼:

視頻屬性的無限延伸

一個擁有億級數據量的短視頻app,視頻存在各種屬性(是否加鎖、是否特效等等),需要做各種標記。數據量大又無限延伸, BitMap可能會達到瓶頸,我們考慮用分片來處理。

key:由屬性id+視頻分片id組成。value:按照視頻id對分片 來決定偏移量offset



以上只是舉了幾個典型的例子,具體情況具體分析該如何設計key 和 offset。

避坑

bitcout bitpos 的 start end 都是 字節索引

有圖有真相:



點關注 不迷路

以上就是這篇的全部內容,能看到這裡的都是 人才

如果你從本篇內容有收穫,求 點贊,求 關注,求 轉發 ,讓更多的人學習到。

如果本文有任何錯誤,請批評指教,不勝感激 !