目录
- 1、bitmaps
- 介绍
- 应用场景
- 使用
- 2、hyperloglogs
- 介绍
- 应用场景
- 使用
- 3、geospatial
- 介绍
- 应用场景
- 使用
- github地址
添加工具类SpringUtils
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
}
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> c) {
return getApplicationContext().getBean(c);
}
public static <T> T getBean(String name, Class<T> c) {
return getApplicationContext().getBean(name, c);
}
}
位图,基于最小的单位bit进行存储,设置时候时间复杂度O(1)、读取时候时间复杂度O(n),占用空间小。bit映射被限制在512MB之内,所以最大是2^32位。
生活中有着两种状态的场景,比如用户每日是否登录,用户是否在线、是否有网购记录,员工是否打卡等具有两种状态的场景,我们可以使用bitmaps来进行记录、查询、统计等等功能。
@Test
public void testBitMaps(){
//位图使用
//此处必须使用StringRedisTemplate,否则bitcount功能失效
StringRedisTemplate stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);
String key = "sign";
ValueOperations operations = stringRedisTemplate.opsForValue();
stringRedisTemplate.delete(key);
System.out.println("key是否存在:"+stringRedisTemplate.hasKey(key));
operations.setBit(key,0,true);//设置新值返回旧值
operations.setBit(key,1,true);
operations.setBit(key,2,false);
operations.setBit(key,3,true);
operations.setBit(key,4,true);
operations.setBit(key,5,false);
operations.setBit(key,6,false);
System.out.println(operations.getBit(key,4));//获取key对应的第5个位的值
System.out.println(operations.getBit(key,6));//获取key对应的第7个位的值
System.out.println(operations.getBit(key,7));//获取key对应的第8个位的值,如果不存在则返回false
System.out.println(operations.getBit(key,3));//获取key对应的第4个位的值
//统计key中value为true的数量
long count = (long)stringRedisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
System.out.println(count);
//统计key中指定范围内value为true的数量
count = (long)stringRedisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes(),1,5));
System.out.println(count);
}
HyperLogLog是一个用于统计唯一性事物数量的概率性数据结构(专业的说这叫估算集合的基数)。通常统计总数需要消耗与数量成正比例的存储空间,为了避免重复统计一个项多次你需要把你已经统计过的项记录下来,然而存在一种算法,损耗一定的精确度来节省存储空间,用一种带有一定误差的估算方式,在redis的实现中,这种误差小于1%。这种算法的魔力在于,你不再需要使用和已存储元素的数目成比例的存储空间,取而代之只使用固定数目的内存,在最差的情况下也仅仅需要12Kb的内存!如果你的元素数目很少,消耗的内存会更少。
统计注册的IP数,每日访问数,每天在线人数,搜索词条数等类似场景。
@Test
public void testHyperLogLog(){
String key1 = "HyperLogLog1";
String key2 = "HyperLogLog2";
String desKey = "desHyperLogLog";
HyperLogLogOperations operations = redisTemplate.opsForHyperLogLog();
//给基数添加元素
operations.add(key1, "a", "b", "c");
operations.add(key2, "d", "e", "f","g");
//返回HyperLogLog的基数值
Long size = operations.size(key1);
System.out.println(key1+"的基数值: " + size);
size = operations.size(key2);
System.out.println(key2+"的基数值: " + size);
//获取两个基数集合的并集
size = operations.union(desKey,key1,key2);
System.out.println(desKey+"的基数值: " + size);
}
将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
比如微信位置共享,附近的人等地图功能。
@Test
public void testGeoSpatial(){
//reids 3.2版本之后支持
String citys = "citys";
String chengdu = "chengdu";
String beijing = "beijing";
String chongqing = "beijing";
String luzhou = "beijing";
GeoOperations<String, String> geoOperations = redisTemplate.opsForGeo();
geoOperations.add(citys,new RedisGeoCommands.GeoLocation<String>(chengdu,new Point(104,30)));
geoOperations.add(citys,new Point(116,40),beijing);
geoOperations.add(citys,new Point(106,29),chongqing);
geoOperations.add(citys,new Point(105,25),luzhou);
System.out.println(geoOperations.position(citys, "chengdu"));//获取成都经纬度
System.out.println(geoOperations.distance(citys, chengdu, beijing));//获取两地距离
Point center = new Point(104,30);//定义中心点
Distance radius = new Distance(800, Metrics.KILOMETERS);//定义范围
Circle within = new Circle(center, radius);
//返回范围内的城市
System.out.println(geoOperations.radius(citys, within));
//根据距离排序,返回最近的两个
RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.
newGeoRadiusArgs().includeDistance().limit(2).sortAscending();
System.out.println(geoOperations.radius(citys, within, args));
}
https://github.com/JsonTom888/database/tree/main/springboot_redis