HyperLogLog
(1)采用一种基数算法,用于完成独立总数的统计。
(2)占据空间小,无论统计多少个数据,只占12k的内存空间。
(3)不精确的统计算法,标准误差为0.81%。
Bitmap
(1)不是一种独立的数据结构,实际上就是字符串。
(2)支持按位存取数据,可以将其看成是byte数组。
(3)适合存储索大量的连续的数据的布尔值。
//统计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);
}
// 将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);
}
// 统计一组数据的布尔值(比如全班签到次数)
@Test
public void testBitMap(){
String redisKey = "test:bmp: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()); //统计这组Bytes里1的个数
}
});
System.out.println(obj);
}
//统计3组数据(比如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:02";
redisTemplate.opsForValue().setBit(redisKey3,2,true);
redisTemplate.opsForValue().setBit(redisKey3,3,true);
redisTemplate.opsForValue().setBit(redisKey3,4,true);
String redisKey4 = "test:bm:02";
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));
}