Redis三种数据类型
介绍得这三种数据类型常用于特定得业务场景。现做简单记录,日后实际用到补充细节
Hyperloglog基数统计
- 操作:redisTemplate模板调用opsForHyperloglog方法即可获取操作对象进行操作
- 场景:适用于对有相同数据进行计数得统计。如统计出软件得下载数,要区分开用户一个用户可能会下载多次。使用该数据类型便可以进行去重统计得效果。
- 数据结构:优点在于其占用内存少。量级为2^64元素占用内存12k即可。上述统计下载量通常做法为存储set将用户id作为标志进行判断,但是用户id是不必要数据比较占用内存。缺点:存在一定得错误误差大概0.8%,小数据量时没有误差。
- 案例
@Resource
private StringRedisTemplate stringRedisTemplate;
/**使用hyperloglog*/
@Test
void hyperTest(){
final HyperLogLogOperations<String, String> hyper = stringRedisTemplate.opsForHyperLogLog();
//创建一个统计出下载次数得:统计华为应用商店下载次数
hyper.add("downloadCount","user1","user1","user2","user5");
hyper.add("downloadCount","user100","user2","user7");
Long downloadCount = hyper.size("downloadCount");
System.out.println(downloadCount);
//创建第二个统计出下载次数得:统计oppo商店下载次数
hyper.add("downloadCount1","user1","user8","user2","user9");
//对两个或多个进行合并基数统计:统计总下载次数(去除相同用户得下载次数)
Long union = hyper.union("downloadCounts", "downloadCount1", "downloadCount");
System.out.println(union);
}
bitmaps位
- 操作:redisTemplate模板未提供操作,可使用原生jedis进行操作使用。
- 场景:适用于有两个状态得统计和记录工作
- 数据结构:按位存储,统计状态时占用内存非常少。例如飞书团队成员一年打卡天数时365天=365位=45位不到1k就可以完成统计
- 案例
#统计打卡天数命名位daka,该值即可以定位到具体得团队得某个人
#第一个数可以当作具体到哪一天,第二个数为0或者1用于记录是否打卡
yh:0>setbit daka 1 0
"0"
yh:0>setbit daka 2 0
"0"
yh:0>setbit daka 3 1
"0"
yh:0>setbit daka 4 0
"0"
yh:0>setbit daka 5 1
"0"
yh:0>setbit daka 6 1
"0"
yh:0>setbit daka 7 1
"0"
# 获取某天是否打卡
yh:0>getbit daka 7
"1"
yh:0>getbit daka 1
"0"
# 对整个daka进行统计计算为1得个数,即打卡得总天数
yh:0>bitcount daka
"4"
yh:0>
geospatial:地理位置
- 操作:redisTemplate模板提供操作
- 场景:适用于关于位置相关得操作
- 数据结构:本质上是ZSet进行得封住操作
- 案例
/**
* 录入中国城市的经纬度信息到redis中*/
@Test
void importDataTest() throws IOException {
final BoundGeoOperations<String, String> geo = stringRedisTemplate.boundGeoOps("china:ningxia");
geo.add(new Point(106.278179,38.46637),"yc");
geo.add(new Point(106.33999,38.10266),"szs");
geo.add(new Point(105.189568,37.514951),"zw");
}
/**
* 使用提供的geo命令完成相关功能*/
@Test
void useDataTest() throws IOException {
final BoundGeoOperations<String, String> geo = stringRedisTemplate.boundGeoOps("china:ningxia");
//1.查看两个地点之间得直线距离
Distance distance = geo.distance("yc", "zw");
System.out.println(distance.getValue());//142491.8275
//百度结果143km
//2.查看某地点半径范围内附近得人.以及做相关统计
GeoResults<RedisGeoCommands.GeoLocation<String>> radius = geo.radius(new Circle(new Point(106.278179, 38.46637), new Distance(100000)));
System.out.println(radius);
//GeoResults: [averageDistance: 0.0, results: GeoResult [content: RedisGeoCommands.GeoLocation(name=石嘴山市, point=null), distance: 0.0, ],GeoResult [content: RedisGeoCommands.GeoLocation(name=银川市, point=null), distance: 0.0, ]]
GeoResults<RedisGeoCommands.GeoLocation<String>> results = geo.radius("yc", new Distance(100, Metrics.KILOMETERS));
System.out.println(results);
}