当数据量较大,但是不要求精确值的时候可以使用HyperLogLog
使用
//统计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);
}
//合并三组数据,并统计合并后的独立总数
@Test
public void testHyperLogLogUnion(){
String redisKey2="test:hll:02";
String redisKey3="test:hll:03";
String redisKey4="test:hll:04";
for(int i=1;i<=10000;i++){
redisTemplate.opsForHyperLogLog().add(redisKey2,i);
}
for(int i=5001;i<=15000;i++){
redisTemplate.opsForHyperLogLog().add(redisKey3,i);
}
for(int i=10000;i<=20000;i++){
redisTemplate.opsForHyperLogLog().add(redisKey4,i);
}
String union="test:hll:05";
redisTemplate.opsForHyperLogLog().union(union,redisKey2,redisKey3,redisKey4);
long size=redisTemplate.opsForHyperLogLog().size(union);
System.out.println(size);
}
可以用于统计网站的签到,用户每天登陆了没有
使用
//统计一组数据的布尔值
@Test
public void testBitmap(){
String redisKey="test:bm:01";
//存储(没有存储的位置默认是false,所以只需要存储true即可)
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));
//统计true个数
Object execute = redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
return connection.bitCount(redisKey.getBytes());
}
});
System.out.println(execute);
}
//统计三组数据的布尔值,并对三组数据进行OR运算
@Test
public void testBitmap2(){
String redisKey2="test:bm:02";
String redisKey3="test:bm:03";
String redisKey4="test:bm:04";
redisTemplate.opsForValue().setBit(redisKey2,0,true);
redisTemplate.opsForValue().setBit(redisKey2,1,true);
redisTemplate.opsForValue().setBit(redisKey2,2,true);
redisTemplate.opsForValue().setBit(redisKey2,2,true);
redisTemplate.opsForValue().setBit(redisKey2,3,true);
redisTemplate.opsForValue().setBit(redisKey2,4,true);
redisTemplate.opsForValue().setBit(redisKey2,4,true);
redisTemplate.opsForValue().setBit(redisKey2,5,true);
redisTemplate.opsForValue().setBit(redisKey2,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));
}