在日常開發過程中,常常會有一些 bool 類型資料需要存取。例如記錄用戶一年內簽到的次數,簽了是 1,沒簽是 0。如果使用 key-value 來存儲,那麼每個用戶都要記錄 365 次,當用戶成百上億時,需要的存儲空間將非常巨大。解決這個問題,可以使用redis中的點陣圖。
點陣圖(bitmap)同樣屬於 string 資料型別。 Redis 中一個字串類型的值最多能儲存 512 MB 的內容,每個字串由多個位元組組成,每個位元組又由 8 個 Bit 位元組成。點陣圖結構正是使用「位元」來實現儲存的,它透過將位元位元設為 0 或 1來達到資料存取的目的,這大大增加了 value 儲存數量,它儲存上限為2^32。
點陣圖本質上就是一個普通的位元組串,也就是 bytes 數組。可以透過使用getbit/setbit 指令處理該位圖數組,其結構如下所示:
#位圖通常用於一些特定應用,例如追蹤使用者簽到次數或登錄次數。上圖是表示一位使用者 10 天內來網站的簽到次數,1 代表簽到,0 代表未簽到,這樣可以很輕鬆地統計出使用者的活躍程度。使用點陣圖記錄每一筆記錄僅佔用一個 bit 位,相對於直接使用字串,大幅減少了記憶體空間的使用率。
Redis 官方也做了一個實驗,他們模擬了一個擁有1 億2 千8 百萬用戶的系統,然後使用Redis 的位圖來統計“日均用戶數量”,最終所用時間的約為50ms,且僅佔用16 MB記憶體。
如果使用字串類型存儲,某個網站必須要記錄一個使用者一年的簽到記錄,那麼需要 365 個鍵值對。若使用點陣圖存儲,用戶簽到就存 1,否則存 0。最後會產生 00010101… 這樣的儲存結果,其中每天的記錄只佔一位,一年就是 365 位,約 46 個位元組。如果只想統計使用者簽到的天數,那麼統計 1 的數量即可。
點陣圖操作的優勢,相較於字串而言,它不僅效率高,而且還非常的節省空間。
Redis 的位數組是自動擴展的,如果設定了某個偏移位置超出了現有的內容範圍,位數組就會自動擴充。
用來設定或清除某一位上的值,其傳回值是原來位元上儲存的值。 key 在初始狀態下所有的位元都是 0 ,範例如下:
SETBIT key offset value
其中 offset 表示偏移量,從 0 開始。範例如下:
127.0.0.1:6379> SET user:1 a OK #设置偏移量offset为0 127.0.0.1:6379> SETBIT user:1 0 1 (integer) 0 #当对应位的字符是不可打印字符,redis会以16进制形式显示 127.0.0.1:6379> GET user:1 "\xe1"
用來取得某一位上的值。範例如下:
127.0.0.1:6379> GETBIT user:1 0 (integer) 1
當偏移量 offset 比字串的長度大,或當 key 不存在時,傳回 0。
redis> EXISTS bits (integer) 0 redis> GETBIT bits 100000 (integer) 0
統計指定位元區間上,值為 1 的個數。語法格式如下:
BITCOUNT key [start end]
範例如下:
127.0.0.1:6379> BITCOUNT user:1 (integer) 8
只需指定 start 和 end 參數,即可僅對特定位元組進行計數。 start 和 end 參數和 GETRANGE 指令的參數類似,都可以使用負數,例如 -1 表示倒數第一個位, -2 表示倒數第二個位。 .
對一個或多個儲存二進位位元的字串key 進行位元操作,並將結果儲存到destkey 上
運算可以為四種中的任一種:AND、OR、NOT、XOR
BITOP AND destkey key [key …] ,對一個或多個key 求邏輯並,並將結果儲存到destkey 。
BITOP OR destkey key [key …] ,對一個或多個 key 求邏輯或,並將結果儲存到 - destkey 。
BITOP XOR destkey key [key …] ,對一個或多個 key 求邏輯異或,並將結果儲存到 destkey 。
BITOP NOT destkey key ,對給定 key 求邏輯非,並將結果儲存到 destkey 。
除了 NOT 運算之外,其他運算都可以接受一個或多個 key 作為輸入。
每日活躍統計創建一個bitmap鍵,當用戶活躍了根據用戶id的偏移量來設定
對應的位元為1
每個使用者建立一個點陣圖的鍵,以某一天為基礎,之後的天數距離這一天的天數為偏移量,
如果使用者點選了簽到,則設定對用的偏移位元為1。
以上是Redis中的Bitmap如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!