①. 聚合统计
统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计交并差集和聚合函数的应用
②. 排序统计:如抖音视频最新评论留言的场景,请你设计一个展现列表。考察你的数据结构和设计思路 - list、zset
③. 二值统计:集合元素的取值就只有0和1两种。在钉钉上班签到打卡的场景中,我们只用记录有签到(1)或没签到(0) - bitmap
④. 基数统计:指统计⼀个集合中不重复的元素个数 - hyperloglog

512M = 4294967296 / 8 /1024 /1024
127.0.0.1:6379> setbit bitmap1 0 1 # 111001111
(integer) 0
127.0.0.1:6379> setbit bitmap1 1 1
(integer) 0
127.0.0.1:6379> setbit bitmap1 2 1
(integer) 0
127.0.0.1:6379> setbit bitmap1 5 1
(integer) 0
127.0.0.1:6379> setbit bitmap1 6 1
(integer) 0
127.0.0.1:6379> setbit bitmap1 7 1
(integer) 0
127.0.0.1:6379> setbit bitmap1 8 1
(integer) 0
127.0.0.1:6379> getbit bitmap1 0
(integer) 1
127.0.0.1:6379> strlen bitmap1 # 2个字节
(integer) 2
127.0.0.1:6379> bitcount bitmap1 # 7个长度
(integer) 7
127.0.0.1:6379> bitfield bitmap1 get u2 0 # u:表示无符号,2查询两个 0:下标开始位置
1) (integer) 3 # 11 = 1+2=3
127.0.0.1:6379> bitfield bitmap1 get u3 0
1) (integer) 7 # 111=1+2+4=7
127.0.0.1:6379> bitpos bitmap1 1 # 1开始的位置
(integer) 0
127.0.0.1:6379> bitpos bitmap1 0 # 0开始的位置
(integer) 3
127.0.0.1:6379> 



strlen:统计字节数占用多少,不是字符串长度而是占据几个字节,超过8位后自己按照8位一组一byte再扩容

bitcount作用

bitop作用

redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 0 1 # bits-2 = 1101
(integer) 0
redis> SETBIT bits-2 1 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP AND and-result bits-1 bits-2
(integer) 1
redis> GETBIT and-result 0 # and-result = 1001
(integer) 1
redis> GETBIT and-result 1
(integer) 0
redis> GETBIT and-result 2
(integer) 0
redis> GETBIT and-result 3
(integer) 1签到功能设计的mysql表
create table `tb_sign`(
`id` bigint(20) unsigned NOT NULL COMMENT '主键id',
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户id',
`year` year(4) NOT NULL COMMENT '签到的年',
`month` tinyint(2) NOT NULL COMMENT '签到的月',
`date` date NOT NULL COMMENT '签到的日期',
`is_backup` tinyint(1) unsigned DEFAULT NULL COMMENT '是否签到',
PRIMARY KEY(`id`)
)ENGINE=INNODB COMMENT='签到表';我们如何能够简化一点呢?其实可以考虑小时候一个挺常见的方案,就是小时候,咱们准备一张小小的卡片,你只要签到就打上一个勾,我最后判断你是否签到,其实只需要到小卡片上看一看就知道了

我们可以采用类似这样的方案来实现我们的签到需求 - bitmap(位图)入肉片;

实现签到接口,将当前用户当天签到信息保存到Redis中。
思路:我们可以把年和月作为bitMap的key,然后保存到一个bitMap中,每次签到就到对应的位上把数字从0变成1,只要对应是1,就表明说明这一天已经签到了,反之则没有签到
@PostMapping("/user/sign/{userId}")
public void sign(@PathVariable(value = "userId") String userId){
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
String month = new SimpleDateFormat("yyyyMM").format(new Date());
String key=signKey+month;
int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
redisTemplate.opsForValue().setBit(key,monthDay-1,true);
}什么叫做连续签到天数?
如何得到本月到今天为止的所有签到数据?(使用BITFIELD)
BITFIELD key GET u[dayOfMonth] 0如何从后向前遍历每个bit位?
代码实现
@PostMapping("/user/signCount/{userId}")
public void signCount(@PathVariable(value = "userId") String userId){
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
String month = new SimpleDateFormat("yyyyMM").format(new Date());
String key=signKey+month;
int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
// 5.获取本月截止今天为止的所有的签到记录,返回的是一个十进制的数字 BITFIELD sign:5:202203 GET u20 0
List<Long> result = redisTemplate.opsForValue().bitField(
key,
BitFieldSubCommands.create()
.get(BitFieldSubCommands.BitFieldType.unsigned(monthDay)).valueAt(0)
);
if (result == null || result.isEmpty()) {
// 没有任何签到结果
return;
}
Long num = result.get(0);
if (num == null || num == 0) {
return;
}
// 6.循环遍历
int count = 0;
while (true) {
// 6.1.让这个数字与1做与运算,得到数字的最后一个bit位 // 判断这个bit位是否为0
if ((num & 1) == 0) {
// 如果为0,说明未签到,结束
break;
}else {
// 如果不为0,说明已签到,计数器+1
count++;
}
// 把数字右移一位,抛弃最后一个bit位,继续下一个bit位
num >>>= 1;
}
System.out.println(count);
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。