Redis:BitMap使用(用户签到)

╰+攻爆jí腚メ 2024-03-24 08:41 128阅读 0赞

我们按月来统计用户签到信息,签到记录为1,未签到则记录为0.

把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态,这种思路就称为位图(BitMap)。

Redis中是利用string类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是 2^32个bit位。

  1. // bitmap添加
  2. // 获取日期
  3. LocalDateTime now = LocalDateTime.now();
  4. // 拼接key
  5. String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
  6. // 获取今天是本月的第几天
  7. int dayOfMonth = now.getDayOfMonth();
  8. // 写入Redis SETBIT key offset 1
  9. stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
  10. // bitmap统计或者连续签到
  11. // 获取日期
  12. LocalDateTime now = LocalDateTime.now();
  13. // 拼接key
  14. String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
  15. // 获取今天是本月的第几天
  16. int dayOfMonth = now.getDayOfMonth();
  17. // 获取本月截止今天为止的所有的签到记录,返回的是一个十进制的数字
  18. // BITFIELD sign:5:202203 GET u14 0
  19. List<Long> result = stringRedisTemplate.opsForValue().bitField(
  20. key,
  21. BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
  22. );
  23. if (result == null || result.isEmpty()) {
  24. // 没有任何签到结果
  25. return Result.ok(0);
  26. }
  27. Long num = result.get(0);
  28. if (num == null || num == 0) {
  29. return Result.ok(0);
  30. }
  31. // 循环遍历
  32. int count = 0;
  33. while (true) {
  34. // 让这个数字与1做与运算,得到数字的最后一个bit位
  35. // 判断这个bit位是否为0
  36. if ((num & 1) == 0) {
  37. // 如果为0,说明未签到,结束
  38. break;
  39. }else {
  40. // 如果不为0,说明已签到,计数器+1
  41. count++;
  42. }
  43. // 把数字右移一位,抛弃最后一个bit位,继续下一个bit位
  44. num >>>= 1;
  45. }
  46. return Result.ok(count);

发表评论

表情:
评论列表 (有 0 条评论,128人围观)

还没有评论,来说两句吧...

相关阅读

    相关 签到

    签到 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^\_^ 题目描述 ACM is just a game.