Redis-bitmaps
·什麼是bitmaps
Bitmaps並不是實際的數據類型,而是定義在String類型上的一個面向字節操作的集合。因爲字符串是二進制安全的塊,他們的最大長度是512M。
字節操作可以分爲兩類:恆定時間的單個字節操作如將一個字節設置爲1或者0、或者獲取一個字節的值,和批量字節操作如在給定的字節範圍內計算設置字節的數量。
Redis中bitmaps的常用操作
基本使用
Redis 的位數組是自動擴展,如果設置了某個偏移位置超出了現有的內容範圍,就會自動將位數組進行零擴充。
1. setbit key offset value
- 給位圖指定索引設置值,返回該索引位置的原始值
(1).“零存零取”
(2).“整存零取”
如果對應位的字節是不可打印字符,redis-cli 會顯示該字符的 16 進制形式。
2. getbit key offset
- 獲取位圖指定索引的值
- 不存在的 key 被當成是空字符串來處理
4. bitpos key targetBit [start] [end] (起始版本:2.8.7)
- 計算位圖指定範圍(start到end,單位爲字節,如果不指定就是獲取全部)第一個偏移量對應的值等於targetBit的位置。
5. bitop and|or|not|xor destkey key [key...]
- 做多個bitmap的and(交集)、or(並集)、not(非)、xor(異或)操作並將結果保存到destkey中。
Redis 的位數組是自動擴展,如果設置了某個偏移位置超出了現有的內容範圍,就會自動將位數組進行零擴充。
6.魔術指令 bitfield
前文我們設置 (setbit) 和獲取 (getbit) 指定位的值都是單個位的,如果要一次操作多個位,就必須使用管道來處理。
不過 Redis 的 3.2 版本以後新增了一個功能強大的指令,有了這條指令,不用管道也可以一次進行多個位的操作。
bitfield 有三個子指令,分別是 get/set/incrby,它們都可以對指定位片段進行讀寫,但是最多隻能處理 64 個連續的位,如果超過 64 位,就得使用多個子指令,bitfield 可以一次執行多個子指令。
所謂有符號數是指獲取的位數組中第一個位是符號位,剩下的纔是值。如果第一位是 1,那就是負數。無符號數表示非負數,沒有符號位,獲取的位數組全部都是值。有符號數最多可以獲取 64 位,無符號數只能獲取 63 位 (因爲 Redis 協議中的 integer 是有符號數,最大 64 位,不能傳遞 64 位無符號值)。如果超出位數限制,Redis 就會告訴你參數錯誤。
接下來一次執行多個子指令:
然後我們使用 set 子指令將第二個字符 e 改成 a,a 的 ASCII 碼是 97,返回舊值。
再看第三個子指令 incrby,它用來對指定範圍的位進行自增操作。既然提到自增,就有可能出現溢出。如果增加了正數,會出現上溢,如果增加的是負數,就會出現下溢出。Redis 默認的處理是折返。如果出現了溢出,就將溢出的符號位丟掉。如果是 8 位無符號數 255,加 1 後就會溢出,會全部變零。如果是 8 位有符號數 127,加 1 後就會溢出變成 -128。
接下來實踐一下這個子指令 incrby :
bitfield 指令提供了溢出策略子指令 overflow,用戶可以選擇溢出行爲,默認是折返 (wrap),還可以選擇失敗 (fail) 報錯不執行,以及飽和截斷 (sat),超過了範圍就停留在最大最小值。overflow 指令隻影響接下來的第一條指令,這條指令執行完後溢出策略會變成默認值折返 (wrap)。
飽和截斷 SAT
失敗不執行 FAIL