1.场景
- 实现记录用户哪天进行了登录,每天只记录是否登录过,重复登录状态算已登录。不需要记录用户的操作行为,不需要记录用户上次登录时间和IP地址(这部分以后需要可以单独拿出来存储)
- 区分用户类型
- 查询数据需要精确到天
2.分析
直接使用文件或者数据库会导致文件或数据急剧增长,都不太合适,最终考虑使用redis位图加上数据库做数据备份
3.redis位图介绍
简介
-
我们都知道8bit = 1b = kb,bitmap就是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态。
一个bit的值,或者是0,或者是1;也就是说一个bit能存储的最多信息是2。 -
位图并不是一种特殊的数据结构,其实本质上是二进制字符串,也可以看做是 byte 数组。可以使用普通的 get/set 直接获取和设置整个位图的内容,也可以使用位图操作 getbit/setbit 等将 byte 数组看成「位数组」来处理。
位图的优势
- 基于最小的单位bit进行存储,所以非常省空间。
- 设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的
- 二进制数据的存储,进行相关计算的时候非常快
- 方便扩容
可使用场景
- 用户签到
- 用户在线状态
- 统计活跃用户
- 各种状态值
常用命令
- SETBIT
对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
SETBIT key offset value
offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。
- GETBIT
对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
GETBIT key offset
- BITCOUNT
计算给定字符串中,被设置为 1 的比特位的数量。
BITCOUNT key
- BITPOS
返回位图中第一个值为 bit 的二进制位的位置。
BITPOS key bit [start] [end]
- BITOP
对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
BITOP operation destkey key [key …]
operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种
BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
- BITFIELD
bitfield 有三个子指令,分别是 get/set/incrby,它们都可以对指定位片段进行读写,
但是最多只能处理 64 个连续的位,如果超过 64 位,就得使用多个子指令,bitfield
可以一次执行多个子指令。
4.设计
Key结构:前缀_年Y-月m_用户类型_用户ID
标准Key:KEYS loginLog_2017-10_client_1001
检索全部:KEYS loginLog_*
检索某年某月全部:KEYS loginLog_2017-10_*
检索单个用户全部:KEYS loginLog_*_client_1001
检索单个类型全部:KEYS loginLog_*_office_*...
每条BitMap记录单个用户一个月的登录情况,一个bit位表示一天登录情况。
设置用户1001,217-10-25登录:SETBIT loginLog_2017-10_client_1001 25 1
获取用户1001,217-10-25是否登录:GETBIT loginLog_2017-10_client_1001 25
获取用户1001,217-10月是否登录:BITCOUNT loginLog_2017-10_client_1001
获取用户1001,217-10/9/7月是否登录:BITOP OR stat loginLog_2017-10_client_1001 loginLog_2017-09_client_1001 loginLog_2017-07_client_1001...
5.数据库表结构
每周同步一次数据到数据库,表中一条数据对应一个BitMap,记录一个月数据。每次更新已存在的、插入没有的
6.参考资料
https://www.cnblogs.com/bndong/p/7677781.html
https://redis.readthedocs.io/en/2.6/string/bitop.html
https://www.jianshu.com/p/ddc920d3e6e0