项目-23-Redis高级数据类型

本文介绍Redis中的两种高级数据类型:HyperLogLog和Bitmap。HyperLogLog适用于统计独立元素的总数,如UV统计,其占用空间小且有轻微的统计误差。Bitmap则用于存储大量连续数据的布尔值,例如用户的签到记录。文章通过示例展示了这两种数据类型的使用方法。

Redis高级数据类型

1. HyperLoglog 超级日志

  • 采用一种基数算法,用于完成独立总数的统计。[统计UV]
  • 占据空间小,无论统计多少个数据,只占12K的内存空间。
  • 不精确的统计算法,标准误差为0.81%。

2. Bitmap 位图

  • 不是一种独立的数据结构,实际上就是字符串。
  • 支持按位存取数据,可以将其看成是byte数组。
  • 适合存储大量的连续的数据的布尔值。[统计签到]

3. 实例

//统计20万个重复数据的独立总数
@Test
public void testHyperLogLog(){
    String redisKey = "test:hll:01";
    // 存十万个不重复的数据 [0-99999]
    for (int i = 0; i < 100000; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey,i);  
    }
	// 再随机存放范围在[0-99999]的十万个数据
    for (int i = 0; i < 100000; i++) {
        int j = (int) (Math.random() * 100000 + 1);
        redisTemplate.opsForHyperLogLog().add(redisKey,j);
    }
    // long : opsForHyperLogLog().size(redisKey)输出不重复数据的总数,会有误差
    System.out.println(redisTemplate.opsForHyperLogLog().size(redisKey));
}

//将3组数据合并,之后再统计合并后重复数据的独立总数
@Test
public void testHyperLogLogUnion(){
    String redisKey2 = "test:hll:02";
    for (int i = 0; i < 10000; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey2,i);
    }

    String redisKey3 = "test:hll:03";
    for (int i = 5001; i < 15000; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey3,i);
    }


    String redisKey4 = "test:hll:04";
    for (int i = 10001; i < 20000; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey4,i);
    }
	// 新索引
    String unionKey = "test:hll:union";
    // opsForHyperLogLog().union  将3个索引对应的数据进行合并,存入对应的新索引
    redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);
    System.out.println(redisTemplate.opsForHyperLogLog().size(unionKey));
}

@Test
//统计数据的布尔值个数
public void testBitMap(){
    String redisKey = "test:bm:01";
    //按位存储数据
    redisTemplate.opsForValue().setBit(redisKey, 1, true);
    redisTemplate.opsForValue().setBit(redisKey, 3, true);

    //获取某位的值
    redisTemplate.opsForValue().getBit(redisKey, 0);
    redisTemplate.opsForValue().getBit(redisKey, 1);

    //统计总数
    Object result = redisTemplate.execute(new RedisCallback() {
        @Override
        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
            return redisConnection.bitCount(redisKey.getBytes());
        }
    });
    System.out.println(result);
}


//统计3组数据的布尔值,并对其进行OR运算
@Test
public void testBitMapOper(){
    String redisKey2 = "test:bm:02";
    //存储数据
    redisTemplate.opsForValue().setBit(redisKey2, 1, true);
    redisTemplate.opsForValue().setBit(redisKey2, 2, true);

    String redisKey3 = "test:bm:03";
    //存储数据
    redisTemplate.opsForValue().setBit(redisKey3, 3, true);
    redisTemplate.opsForValue().setBit(redisKey3, 4, true);

    String redisKey4 = "test:bm:04";
    //存储数据
    redisTemplate.opsForValue().setBit(redisKey4, 5, true);
    redisTemplate.opsForValue().setBit(redisKey4, 6, true);

    String redisKeyOr = "test:bm:or";
    Object result = redisTemplate.execute(new RedisCallback() {
        @Override
        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
            // RedisStringCommands.BitOperation.OR:声明进行OR运算
            redisConnection.bitOp(RedisStringCommands.BitOperation.OR,
                    redisKeyOr.getBytes(), redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes());
            return redisConnection.bitCount(redisKeyOr.getBytes());
        }
    });
    System.out.println(result);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值