问答平台(7),Redis高级数据类型

HyperLogLog

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

应用

统计网站的PV、UV

测试类

  • RedisTests: 增加内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // 统计20万个重复数据的独立总数
    @Test
    public void testHyperLogLog() {
    String redisKey = "test:hll:01";

    for (int i = 1; i <= 100000; i++) {
    redisTemplate.opsForHyperLogLog().add(redisKey, i);
    }

    for (int i = 1; i <= 100000; i++) {
    int random = (int) (Math.random() * 100000 + 1);
    redisTemplate.opsForHyperLogLog().add(redisKey, random);
    }

    Long size = redisTemplate.opsForHyperLogLog().size(redisKey);
    System.out.println(size);
    }

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

    String unionKey = "test:hll:union";
    redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);

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

结果展示

HyperLogLog测试类-图示

HyperLogLog测试类2-图示


Bitmap

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

应用

统计用户的签到

测试类

  • RedisTests: 增加内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    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 redisConnection) throws DataAccessException {
    return redisConnection.bitCount(redisKey.getBytes());
    }
    });

    System.out.println(obj);
    }

    // 统计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 redisConnection) throws DataAccessException {
    redisConnection.bitOp(RedisStringCommands.BitOperation.OR,
    redisKey.getBytes(), redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes());
    return redisConnection.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));
    }

结果展示

BitMap测试类-图示

BitMap测试类2-图示


参考资料


问答平台(7),Redis高级数据类型
https://lcf163.github.io/2020/06/14/问答平台(7),Redis高级数据类型/
作者
乘风的小站
发布于
2020年6月14日
许可协议