牛客网后端项目实战(四十)(Redis高级数据类型介绍)

  • HyperLogLog
    • 采用一种基数算法,用于完成独立总数的统计
    • 占据空间小,无论统计多少个数据,只占12k的内存空间
    • 使用不精确的统计算法,标准误差为0.81%。
  • Bitmap
    • 不是一种独立的数据结构,实际上就是字符串。
    • 支持按位存取数据,可以将其看成是byte数组。
    • 适合存储大量的连续的数据的布尔值
简单语法介绍 HyperLogLog 1、统计20万个重复数据的独立总数.
// 统计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 r = (int) (Math.random() * 100000 + 1); redisTemplate.opsForHyperLogLog().add(redisKey, r); }long size = redisTemplate.opsForHyperLogLog().size(redisKey); System.out.println(size); }

1)把数据储存到Redis:
生成redisKey
调用API:redisTemplate.opsForHyperLogLog().add(redisKey, i)
2)调用API统计独立总数:
edisTemplate.opsForHyperLogLog().size(redisKey);
2、将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); }

1)将三组数据都储存到Redis中
2)调用API合并数据,合并的结果要存放在另一个key里: redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);
3)调用AP统计独立数据
Bitmap
【牛客网后端项目实战(四十)(Redis高级数据类型介绍)】bitmap不是一个新的数据结构,只是String的一种特殊用法,即按位储存。
1、统计一组数据的布尔值
@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); }

1)按位将布尔值存储到字符串中: redisTemplate.opsForValue().setBit(redisKey, 1, true);
参数1,rediskey;参数2,要存储的索引;参数3,要存储的Boolean值
2)查询API,按位查询:redisTemplate.opsForValue().getBit(redisKey, 0)
3)统计,要使用Redis底层的connection
Object obj = redisTemplate.execute(new RedisCallback() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { return connection.bitCount(redisKey.getBytes()); // 调用connection.bitCount( ),要传递byte数组,所以redisKey.getBytes() } });

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()); return connection.bitCount(redisKey.getBytes()); } }); System.out.println(obj); } }

1)按位将布尔值存储到字符串中
2)OR操作,同样要使用Redis底层的connection,此外要把OR操作得到的数据存放到新key里
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()); } });

connection.bitOp():参数1,指定运算符;参数2,指定要存的key;参数3,传递要统计的3组数据

    推荐阅读