0
点赞
收藏
分享

微信扫一扫

常见场景题-Redis的bitmap如何实现签到功能?

Redis 的 bitmap 实现签到系统?

答: 主要讲一下 Redis 原生的 bitmap 的使用方法,以及如何使用 bitmap 来实现签到功能

先来看一下如何使用 redis bitmap 的原生命令实现签到功能:

  • 签到

我们先来设计 key:userid:yyyyMM,那么假如 usera 在2023年10月3日和2023年10月4日签到的话,使用以下命令:

setbit key offset value

在3日签到的话,偏移量应该设置为2,则签到之后为 001

在4日签到的话,偏移量应该设置为3,则3日、4日签到后为0011(第3位和第4位都是1,表示这两天签到了)

在31日签到的话,偏移量应该设置为30,表示向右偏移30位

127.0.0.1:6379> setbit userx:202310 2 1
(integer) 0
127.0.0.1:6379> setbit userx:202310 3 1
(integer) 0
127.0.0.1:6379> setbit userx:202310 30 1
(integer) 0

  • 查看2023年10月哪些天签到了,10月有31天,所以使用u31(31位无符号整数),后边偏移量为0

127.0.0.1:6379> bitfield userx:202310 get u31 0
1) (integer) 402653185

通过 bitfield [key] get u31 0 获取了31位的无符号整数,将该整数402653185转为二进制如下:(可以发现从左向右第4位和第5位位1,表示这两天签到了,也就是3号签到的时候,在setbit key value offset中,偏移量设置了为3,所以向右偏移3为,在第4位上)

402653185 十进制
0011000000000000000000000000001 二进制

通过取出来这个无符号整数,我们在代码中就可以通过位运算来判断某一天是否签到,可以看出,第3、4、31位都是1,表明在这三天都进行了签到

那么如果今天是10月26日,我们想知道10月1日-10月26日有哪些天进行签到,使用如下命令:

127.0.0.1:6379> bitfield userx:202310 get u26 0
1) (integer) 12582912

12582912 转为二进制为:

26位无符号整数:
00110000000000000000000000

那么我们在计算连续签到的次数就可以使用以下方法:

public Integer getContinuousSignCount() {
  /*
  假如今天是 10月26日
  假如通过 redis 的 bitfield userx:202310 get u26 0 命令得到了从1日-26日的签到数据为:12582912
  */
  Long v = 12582912;
  // 这里 26 为今天的日期
  Integer signCount = 0;
  for (int i = 0; i < 26; i ++) {
    if (v & 1 == 0) return signCount;
    signCount ++;
    v >>= 1;
  }
}

举报

相关推荐

0 条评论