7.4 Redis高级数据类型

Redis高级数据类型

HyperLogLog

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

统计数据

编写测试方法,测试20万个重复数据去重之后的个数;

测试结果为95553 存在一点误差可以接受

@Test
public void TestHyperLogLog(){
    String redisKey="Test:hll:001";

    //循环100000次
    for (int i = 0; i <100000 ; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey,i+1);
    }

    //循环100000次
    for (int i = 0; i <100000 ; i++) {
        redisTemplate.opsForHyperLogLog().add(redisKey,i+1);
    }
    System.out.println(redisTemplate.opsForHyperLogLog().size(redisKey));
}

合并数据

测试结果为19833

// 将3组数据合并, 再统计合并后的重复数据的独立总数.
@Test
public void testHyperLogLogUnion() {
    String redisKey2 = "test:hll:02";
    for (int i = 1; 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);
    }

    //统计结果存放到新的key
    String unionKey = "test:hll:union";
    redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);

    long size = redisTemplate.opsForHyperLogLog().size(unionKey);
    System.out.println(size);
}

Bitmap

  • 不是一种独立的数据结构,实际上就是字符串。
  • 支持按位存取数据,可以将其看成是byte数组。
  • 适合存储索大量的连续的数据的布尔值。
  • 默认是0 false
  • 统计 的是 1 true 的个数
// 统计一组数据的布尔值
@Test
public void testBitMap() {
    String redisKey = "test:bm:01";

    // 记录
    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);
}

bool运算

// 统计3组数据的布尔值, 并对这3组数据做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);

    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));
}

版权声明:本文为Qiuyuguohou原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。