Redis之BitSet

前言:

BitSet是Redis中提供的一种二进制数组的数据结构, 利用这种特殊的数据结构可以实现一些特定的场景.
BitSet的数据长这样: [01010010], 存放的是boolean, 且长度为8的倍数 也就是byte的长度. 且只存true, false会自动填充.
Redisson提供的RBitSet还额外提供了 与 或 非 等api.

场景:

现需要记录一个24小时的状态图, 状态可以是: 打开/关闭; 在家/离家; 等等
每15分钟记一次状态, 也可以是10分钟, 30分钟

模型:

value格式:00010100,以每15分钟的统计结果作为1bit
不足8位会自动补0
在这里插入图片描述
写入和读取分离, 缓存实时维护, 查询也只查缓存, 不查数据源
比如说 00:16 和 01:27 检测到状态为打开, 其余时间段为关闭
那么预期的二进制数据为: 01000100

redisson提供了相关的api:

RBitSet bitSet = redissonClient.getBitSet(key);
bitSet.set(index);
bitSet.expire(7, TimeUnit.DAYS);

对应的数组索引为1和6 , 这里就是set(1), set(6). 0(false)会自动填充

BitSet工具类:
/**
 * Redis位图工具类
 * @author Lynn
 * @date 2023/3/13 19:38
 */
@Component
public class BitMapUtil {

    private static RedissonClient redissonClient;

    @Autowired
    public void setRedissonClient(RedissonClient redissonClient) {
        BitMapUtil.redissonClient = redissonClient;
    }

    private static DeviceConfigService deviceConfigService;

    @Autowired
    public void setDeviceConfigService(DeviceConfigService deviceConfigService) {
        BitMapUtil.deviceConfigService = deviceConfigService;
    }

    public static RBitSet getBitSet(String key) {
        return redissonClient.getBitSet(key);
    }

    public static void mergeList(List<StatusBo> result, RBitSet bitSet, long i) {
        if (i <= bitSet.size() - 1) {
            if (bitSet.get(i)) {
                StatusBo bo = StatusBo.builder()
                    .startTime(BitMapUtil.mapIndexToStartDate(i))
                    .endTime(BitMapUtil.mapIndexToEndDate(i))
                    .build();
                result.add(bo);
                while (i < bitSet.size() - 1 && bitSet.get(i + 1)) {
                    bo.setEndTime(BitMapUtil.mapIndexToEndDate(i + 1));
                    i++;
                }
            }
            i++;
            mergeList(result, bitSet, i);
        }
    }

    private static Date mapIndexToStartDate(long index) {
        Map<String, String> globalConfig =
            deviceConfigService.queryBaseConfig(new DeviceConfigDto(), DeviceConfigDimensionEnum.GLOBAL.getCode());
        String config = globalConfig.get(WHOLE_DAY_PROTECT_INTERVAL);
        int step = StringUtils.isNoBlank(config) ? Integer.parseInt(config) / 60000 : 15;
        int minute = (int) (index * step);
        Date now = new Date();
        return new Date(now.getYear(), now.getMonth(), now.getDate(), minute / 60, minute % 60, 0);
    }

    private static Date mapIndexToEndDate(long index) {
        Map<String, String> globalConfig =
            deviceConfigService.queryBaseConfig(new DeviceConfigDto(), DeviceConfigDimensionEnum.GLOBAL.getCode());
        String config = globalConfig.get(WHOLE_DAY_PROTECT_INTERVAL);
        int step = StringUtils.isNoBlank(config) ? Integer.parseInt(config) / 60000 : 15;
        int minute = (int) ((index + 1) * step);
        Date now = new Date();
        return new Date(now.getYear(), now.getMonth(), now.getDate(), minute / 60 < 24 ? minute / 60 : 23,
            minute / 60 < 24 ? minute % 60 : 59, 0);
    }

    public static long mapDateToIndex(Date date) {
        Map<String, String> globalConfig =
            deviceConfigService.queryBaseConfig(new DeviceConfigDto(), DeviceConfigDimensionEnum.GLOBAL.getCode());
        String config = globalConfig.get(WHOLE_DAY_PROTECT_INTERVAL);
        int step = StringUtils.isNoBlank(config) ? Integer.parseInt(config) / 60000 : 15;
        return (date.getHours() * 60 + date.getMinutes()) / step;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值