1、二进制安全
- redis只存储字节流,与外界交互,存取都是字节流,只要双方客户端有统一的编解码,数据就不会被破坏。
- redis拿的是字节流,编码是一个字符一个字节
- redis-cli --raw 连接redis服务,并触发编码器的格式化。如果不格式化,redis只会识别ASCII码的,超出ASCII码,则显示为16进制
2、位图的使用场景
2.1、场景一:统计一段时间内用户的登录天数
-
如果用数据库实现
-
创建表,用户每笔登录都产生一行记录,然后登录登录时间,还有其他数据也需要记录。MySQL数据库表与表时间还需要主外键。算一下成本,表最小,每行存一个ID和登录日期,各自至少4个字节,也得要8个字节,就是说一个用户的一笔登录就要消耗8个字节,那再乘以登录天数,大概200多天,8*200/8=200,即200个字节,表示了一个用户一年的登录状态,然后几百万个用户,成本比较大
-
再来看redis如何实现呢?如果每一天对应一个二进制位,从左到右,第一个二进制位表示第一天,第二个二进制位表示第二天,最多366个二进制位,366/ 8 = 46,即最多用46个字节就表示了一个用户一年的登录状态,乘以100万个用户,则460KB就表示了100万个用户全年的登录状态。举例如下:该用户有3次登录
-
setbit Bob 1 1 Bob用户第2天登录了
-
setbit Bob 7 1 Bob用户第8天登录了
-
setbit Bob 364 1 Bob用户第365天登录了
统计今年最后2周的登录次数为1
bitcount Bob -2 1 ----->结果为1
2.2、场景二:京东618活动,在这一天,给登录的用户送礼物,一个人只能送一件礼物,共需要准备多少礼物
-
电商用户划分为僵尸用户、冷热用户、忠诚用户,每个用户还可能有多个账号。我们怎么去统计呢?其实我们很多用户都没有经常登录,我们统计活跃用户数即可。那么统计活跃用户数时,需要去重,比如1号到3号这期间,不管这个用户登录了1次还是2次,只要登录了就算,这得去重。
用redis的位图来做,用日期当做key,value呢?我们把每个用户的ID映射到一个二进制位上,每一个二进制位都表示一个用户
setbit 20210101 0 1 # 用户Bob登录了,用0号位表示Bob
setbit 20210102 0 1 # 用户Bob还是登录了
setbit 20210102 7 1 # 用户张三登录了,用第8号位表示张三
- 统计结果:
bitop or orkey 20210101 20210102
bitcount orkey 0 -1 # 结果为2,即表示有2个用户登录了