很多應用比如簽到送積分、簽到領取獎勵:
簽到 1 天送 10 積分,連續簽到 2 天送 20 積分,3 天送 30 積分,4 天以上均送 50 積分等如果連續簽到中斷,則重置計數,每月初重置計數顯示使用者某個月的簽到次數在日曆控制元件上展示使用者每月簽到情況,可以切換年月顯示最簡單的設計思路就是利用MySQL儲存簽到資料(t_user_sign),如下:
使用者簽到:往此表插入一條資料,並更新連續簽到天數查詢根據簽到日期查詢統計根據 amount 統計如果這樣存資料,對於使用者量大的應用,db可能扛不住,比如 1000W 使用者,一天一條,那麼一個月就是 3 億資料,非常龐大。
使用bitmapBitmaps,點陣圖,不是 Redis 的基本資料型別(比如 Strings、Lists、Sets、Hashes),而是基於 String 資料型別的按位操作,高階資料型別的一種。Bitmaps 支援最大位數 232 位。使用 512M 記憶體就可以儲存多達 42.9 億的位元組資訊(232 = 4,294,967,296)。
它由一組 bit 位組成,每個 bit 位對應 0 和 1 兩個狀態,雖然內部還是採用 String 型別儲存,但 Redis 提供了一些指令用於直接操作點陣圖,可以把它看作是一個 bit 陣列,陣列的下標就是偏移量。
優點記憶體開銷小、效率高且操作簡單,很適合用於簽到這類場景。比如按月進行儲存,一個月最多 31 天,那麼我們將該月使用者的簽到快取二進位制就是 00000000000000000000000000000000,當某天簽到將 0 改成 1 即可,而且 Redis 提供對 bitmap 的很多操作比如儲存、獲取、統計等指令,使用起來非常方便。
常用命令程式碼實現位運算判斷是否簽到統計使用者簽到情況獲取使用者某月簽到情況,預設當前月,返回當前月的所有日期以及該日期的簽到情況。
SignController
SignService: 獲取某月簽到情況,預設當月:
獲取登入使用者資訊構建 Redis 儲存的 Key獲取月份的總天數(考慮 2 月閏、平年)透過 BITFIELD 指令獲取當前月的所有簽到資料遍歷進行判斷是否簽到,並存入 TreeMap 方便排序總結由於 String 資料型別的最大長度是 512M,所以 String 支援的位數是 2^32 位。512M 表示位元組 Byte 長度,換算成位 bit 需要乘以 8,即 512 2^10 2^10 * 8=2^32; Strings 的最大長度是 512M,還能存更大的資料?當然不能,但是我們可以換種實現思路,就是將大 key 換成小 key,這樣儲存的大小完全不受限制。