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