7.8 Redis advanced data types

There are two redis advanced data types

Insert picture description here

Independent total: A person visits a website many times a day, counts as one visitor (UA), that is, it needs to be deduplicated when counting.
Occupies a small space, but it is not accurate. It is

Insert picture description here


suitable for counting user sign-in, 0-1 problem. For
example, 01 in the first place means that the first day of this year has not arrived. 01 in the second place means that the second day of this year will arrive or not. The 365th place indicates that the 365th day has not arrived. This is continuous.

Both of these are suitable for statistics of website operation data. And it saves memory very much when making statistics, and the efficiency is high.
The two mechanisms and applicable scenarios are different. This section first deals with the grammatical issues.

In RedisTests

Demo hyperLogLog

  // 统计20万个重复数据的独立总数(独立总数即去重以后的数据个数).
    @Test
    public void testHyperLogLog() {
        String redisKey = "test:hll:01";//hll是HyperLogLog缩写

        for (int i = 1; i <= 100000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey, i);
        }//生成十万个不重复数据

        for (int i = 1; i <= 100000; i++) {
            int r = (int) (Math.random() * 100000 + 1);//r为1-十万之间的整数
            redisTemplate.opsForHyperLogLog().add(redisKey, r);
        }//生成十万个不重复数据


        //两次生成十万个不重复数据,即生成了20万个重复数据。去重以后应该还是十万。
        long size = redisTemplate.opsForHyperLogLog().size(redisKey);
        System.out.println(size);
    }

The final result: 99553, the exact value is one hundred thousand, the error is still small

    // 将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++) {//和redisKey2中的数据有一定交叉
            redisTemplate.opsForHyperLogLog().add(redisKey3, i);
        }

        String redisKey4 = "test:hll:04";
        for (int i = 10001; i <= 20000; i++) {//和redisKey3 中的数据有一定交叉
            redisTemplate.opsForHyperLogLog().add(redisKey4, i);
        }
//总共三万条,去重以后只有两万条
        
        String unionKey = "test:hll:union";
        redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);

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

Result: 19833, the exact value is 2w

Demo BitMap
// Count the boolean value of a set of data

@Test
public void testBitMap() {
    String redisKey = "test:bm:01";

    // 记录
    redisTemplate.opsForValue().setBit(redisKey, 1, true);//setBit表示按位存数据的方法1第一位为true
    redisTemplate.opsForValue().setBit(redisKey, 4, true);//第4位为true
    redisTemplate.opsForValue().setBit(redisKey, 7, true);//其余位置默认为0

    // 查询
    System.out.println(redisTemplate.opsForValue().getBit(redisKey, 0));//false
    System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));//true
    System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));//false

    // 统计true的个数
    Object obj = redisTemplate.execute(new RedisCallback() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            return connection.bitCount(redisKey.getBytes());
        }
    });

    System.out.println(obj);
}

Final result:

Insert picture description here


Test 2

// 统计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());//redisKey.getBytes()表示运算结果。redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes()是研做运算的数据
            return connection.bitCount(redisKey.getBytes());
        }
    });

    System.out.println(obj);

    //打印redisKey中的每一个值
    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));
}
Insert picture description here