用户签到
BitMap功能演示
背景
存储用户签到信息表
假设1000w用户,平均每人每年签到10此,一年数据量1亿。
每签到一次使用(8+8+1+1+3+1)22内存,一个月最多600多字节。
BitMap用法
按月统计用户签到信息,签到记录1、未签到0
把每一个bit位对应当月每一天,形成映射关系。用0和1标示业务状态,这种思路称为位图(BitMap)
Redis中利用String类型数据结构实现BitMap,最大上限512M,转化为bit是2^32bit位
BitMap操作命令:
实现签到功能

@Overridepublic Result sign() {//1.获取当前用户登录信息Long userId = UserHolder.getUser().getId();//2.获取日期LocalDateTime now = LocalDateTime.now();//3.拼接keyString keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = USER_SIGN_KEY + userId + keySuffix;//4.获取今天是本月的第几天int dayOfMonth = now.getDayOfMonth();//5.写入Redis SETBIT key offset 1stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);return Result.ok();}
统计连续签到

需求:实现接口,统计当前用户截止当前时间在本月连续签到天数
UserServiceImpl:
@Overridepublic Result signCount() {//1.获取当前用户登录信息Long userId = UserHolder.getUser().getId();//2.获取日期LocalDateTime now = LocalDateTime.now();//3.拼接keyString keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = USER_SIGN_KEY + userId + keySuffix;//4.获取今天是本月的第几天int dayOfMonth = now.getDayOfMonth();//5.获取本月截至今天为止的所有签到记录,返回是一个十进制数 BITFIELD GET u14 0List<Long> result = stringRedisTemplate.opsForValue().bitField(key, BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));//健壮性判断...if(result == null || result.isEmpty()){return Result.ok(0);}Long num = result.get(0);if(num == null || num ==0){return Result.ok(0);}//6.循环遍历int count = 0;while(true){//6.1.让这个数字与1做与运算,得到数字的最后一个bit位 判断这个bit位是否为0if((num & 1) == 0){//0.未签到,结束break;}else{//1.已签到,计数器+1count++;}//数字右移一位,抛弃最后一个bit位num >>>= 1;}return Result.ok(count);}
UV统计
HyperLogLog用法

实现UV统计
@Testvoid testHyperLogLog() {String[] values = new String[1000];int j = 0;for (int i = 0; i < 1000000; i++) {j = i % 1000;values[j] = "user_" + i;if(j == 999){// 发送到RedisstringRedisTemplate.opsForHyperLogLog().add("hl2", values);}}// 统计数量Long count = stringRedisTemplate.opsForHyperLogLog().size("hl2");System.out.println("count = " + count);}
