redis高级数据类型 HyperLogLog 、 Bitmap

本文介绍了Redis中的两种高级数据类型:HyperLogLog和Bitmap。HyperLogLog是一种基数算法,用于统计大量数据的不重复项,占用空间小,适用于去重操作。Bitmap则是一个位图数据结构,适合存储连续的布尔值,可用于签到记录统计等场景。文章通过示例代码展示了如何使用RedisTemplate进行操作,并演示了如何合并多组数据进行统计。
摘要由CSDN通过智能技术生成

redis高级数据类型

HyperLogLog (超级日志)

  • 采用的是一种基数算法,用于完成独立总数的统计
  • 占据空间小,无论统计多少数据,只存12k的内存空间
  • 不准确的统计算法,标准误差在 0.81%

例子: 用于对巨量的数据进行去重复的操作

    // 统计20万个重复数据的独立总数
    @Test
    public void testHyperLogLog(){
        String redisKey = "test:hll:01";
        for (int i = 1; i <= 1000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey,i);
        }
        for (int i = 1; i <= 1000; i++) {
            int r = (int)(Math.random()*100000 + 1);
            redisTemplate.opsForHyperLogLog().add(redisKey,r);
        }
        // 统计重复的结构
        long size = redisTemplate.opsForHyperLogLog().size(redisKey);
        System.out.println(size);
    }
  • 还可以将多组数据,进行合并以后再去重复
    // 将三组数据进行合并 , 再统计他们一共的去重复后的独立总数
    @Test
    public void testHyperLogLogUnion(){
        String redisKey2 = "test:hll:02";
        for(int i=1;i<=1000;i++){
            redisTemplate.opsForHyperLogLog().add(redisKey2,i);
        }
        String redisKey3 = "test:hll:03";
        for(int i=1;i<=1500;i++){
            redisTemplate.opsForHyperLogLog().add(redisKey3,i);
        }
        String redisKey4 = "test:hll:04";
        for(int i=1000;i<=2000;i++){
            redisTemplate.opsForHyperLogLog().add(redisKey4,i);
        }
        // 合并之后会产生一个新的key,所以我们在之前就要进行定义一个新的key
        String unionKey = "test:hll:union";
        redisTemplate.opsForHyperLogLog().union(unionKey,redisKey3,redisKey2,redisKey4);
        long size = redisTemplate.opsForHyperLogLog().size(unionKey);
        System.out.println(size);
    }

Bitmap (位图)

  • 不是一种独立的数据结构,说白了就是一个字符串
  • 支持按位存取数据,可以将其看成是byte数组
  • 适合存储大量的连续的数据的布尔值

例子: 签到记录的统计

    // 统计一组数据的布尔值
    @Test
    public void testBitmap(){
        String redisKey = "test:bm:01";
        // 记录                             key,第几位存值,布尔值
        redisTemplate.opsForValue().setBit(redisKey,1,true);
        redisTemplate.opsForValue().setBit(redisKey,4,true);
        redisTemplate.opsForValue().setBit(redisKey,7,true);
        // 查询
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,0));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,2));
        // 统计多少个数
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.bitCount(redisKey.getBytes());
            }
        });
        System.out.println(obj);
    }
  • 同样的,位图也可以将多组数据进行合并运算,可以进行 与或非 的运算。
    // 统计三组数据的布尔值,同时对三组数据进行做 or 运算
    @Test
    public void testBitmapOperation(){
        String redisKey2 = "test:bm:02";
        redisTemplate.opsForValue().setBit(redisKey2,0,true);
        redisTemplate.opsForValue().setBit(redisKey2,1,true);
        redisTemplate.opsForValue().setBit(redisKey2,2,true);

        String redisKey3 = "test:bm:03";
        redisTemplate.opsForValue().setBit(redisKey3,2,true);
        redisTemplate.opsForValue().setBit(redisKey3,3,true);
        redisTemplate.opsForValue().setBit(redisKey3,4,true);

        String redisKey4 = "test:bm:04";
        redisTemplate.opsForValue().setBit(redisKey4,4,true);
        redisTemplate.opsForValue().setBit(redisKey4,5,true);
        redisTemplate.opsForValue().setBit(redisKey4,6,true);

        // 同理 合并后的结果需要存放在新的地方,所以我们这里建立一个新的key
        String redisKey = "test:bm:or";
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.bitOp(RedisStringCommands.BitOperation.OR,
                        redisKey.getBytes(),redisKey2.getBytes(),redisKey3.getBytes(),redisKey4.getBytes());
                return connection.bitCount(redisKey.getBytes());
            }
        });
        System.out.println(obj);
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,0));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,2));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,3));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,4));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,5));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey,6));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木不会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值