Redis存储经纬度信息的实现

 更新时间:2025年10月30日 11:16:29   作者:it码喽  
在一些向用户提供天气信息的业务场景中,我们通常会通过前端获取用户经纬度信息,传递给后端作为参数进行外部天气接口调用,本文就来详细的介绍一下Redis存储经纬度信息的实现,感兴趣的可以了解一下

适应场景

在一些向用户提供天气信息的业务场景中,我们通常会通过前端获取用户经纬度信息,传递给后端作为参数进行外部天气接口调用,从而获取用户所在位置的天气信息。

但是一旦用户量级上来了或者该功能被频繁触发时,调用外部天气接口的成本会变得非常高昂。但是对于天气信息来说,并不需要每次都实时调用外部接口获取最新的天气信息,因为天气信息的变化频率并不是特别高,甚至相近位置的天气信息也会非常相似。

因此我们可以通过在Redis中存储经纬度信息和对应的天气信息,在每次请求时,先查询Redis中是否存在相近位置的天气信息,如果存在则直接返回缓存的天气信息,如果不存在则调用外部天气接口获取最新的天气信息,并将其存储在Redis中以备下次使用。

设计思路

  1. 经纬度信息存储:使用Redis的地理位置(GEO)数据结构来存储用户的经纬度信息。通过GEOADD命令将经纬度信息添加到Redis中。
  2. 天气信息存储:将天气信息存储在Redis的字符串(STRING)数据结构中,使用经纬度信息作为键,天气信息作为值。
  3. 查询逻辑
    • 当用户请求天气信息时,首先使用GEORADIUS命令查询Redis中是否存在相近位置的经纬度信息。
    • 如果存在,则使用GET命令获取对应的天气信息。
      • 若天气信息存在且未过期,则直接返回该信息。
      • 若天气信息不存在或已过期,则调用外部天气接口获取最新的天气信息,并删除旧的经纬度信息,然后重新存储新的经纬度和天气信息。
    • 如果不存在,则调用外部天气接口获取最新的天气信息,并使用SET命令将其存储在Redis中,同时使用GEOADD命令将经纬度信息添加到Redis中。
  4. 过期策略:为了确保天气信息的时效性,可以为存储的天气信息设置过期时间(TTL),例如30分钟或1小时,超过该时间后需要重新调用外部接口获取最新的天气信息。由于Redis的GEO数据结构不支持直接设置过期时间,可以在发现天气信息过期时,删除对应的经纬度信息。

代码实现

示例代码选用Java语言实现,使用Spring Boot框架。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.2.5</version>
</dependency>
spring:
  redis:
    host: localhost
    port: 6379

引入Spring Data Redis依赖,并在application.yml中配置Redis连接信息。

@Service
public class WeatherService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String WEATHER_GEO_KEY = "weather:locations";
    private static final String WEATHER_KEY_PREFIX = "weather:";
    private static final long WEATHER_TTL = 3600; // 天气信息过期时间,单位秒

    public String getWeather(String latitude, String longitude) {
        // 查询8公里内最近的经纬度信息
        double lon = Double.parseDouble(longitude);
        double lat = Double.parseDouble(latitude);
        Point point = new Point(lon, lat);
        Distance distance = new Distance(8, Metrics.KILOMETERS);
        Circle circle = new Circle(point, distance);

        var geoResults = redisTemplate.opsForGeo().radius(WEATHER_GEO_KEY, circle,
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending().limit(1));

        if (geoResults != null && !geoResults.getContent().isEmpty()) {
            var nearestLocation = geoResults.getContent().get(0);
            String locationKey = nearestLocation.getContent().getName();

            // 获取对应的天气信息
            String weatherKey = WEATHER_KEY_PREFIX + locationKey;
            String cachedWeather = redisTemplate.opsForValue().get(weatherKey);
            if (cachedWeather != null) {
                return cachedWeather; // 返回缓存的天气信息
            } else {
                // 天气信息过期,删除旧的经纬度信息
                redisTemplate.opsForGeo().remove(WEATHER_GEO_KEY, locationKey);
            }
        }

        // 调用外部天气接口获取最新的天气信息
        String newWeatherInfo = fetchWeatherFromExternalApi(latitude, longitude);

        // 存储新的经纬度和天气信息
        String locationKey = latitude + ":" + longitude;
        redisTemplate.opsForGeo().add(WEATHER_GEO_KEY, new Point(lon, lat), locationKey);
        String weatherKey = WEATHER_KEY_PREFIX + locationKey;
        redisTemplate.opsForValue().set(weatherKey, newWeatherInfo, Duration.ofSeconds(WEATHER_TTL));

        return newWeatherInfo;
    }

    private String fetchWeatherFromExternalApi(String latitude, String longitude) {
        // 这里实现调用外部天气接口的逻辑
    }

}

在上述代码中,我们定义了一个WeatherService类,包含了获取天气信息的逻辑。首先通过GEORADIUS命令查询8公里内最近的经纬度信息,如果找到则尝试获取对应的天气信息;如果天气信息不存在或已过期,则调用外部天气接口获取最新的天气信息,并将其存储在Redis中,同时更新经纬度信息。

通过这种方式,我们可以有效地减少对外部天气接口的调用频率,提高系统的响应速度和稳定性。

到此这篇关于Redis存储经纬度信息的实现的文章就介绍到这了,更多相关Redis存储经纬度信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Redis中的List是如何实现的

    详解Redis中的List是如何实现的

    List 的 Redis 中的 5 种主要数据结构之一,它是一种序列集合,可以存储一个有序的字符串列表,顺序是插入的顺序,本文将给大家介绍了一下Redis中的List是如何实现的,需要的朋友可以参考下
    2024-05-05
  • Redis BloomFilter实例讲解

    Redis BloomFilter实例讲解

    这篇文章主要介绍了Redis BloomFilter实例。BloomFilter不需要存储key,节省空间,在某些对保密要求非常严格的场合有优势。想要进一步了解BloomFilter运用实例的小伙伴可以了解一下这篇文章
    2021-09-09
  • Redis键值设计的具体实现

    Redis键值设计的具体实现

    本文主要介绍了Redis键值设计的具体实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Redis实现库存扣减的示例代码

    Redis实现库存扣减的示例代码

    在日常开发中有很多地方都有类似扣减库存的操作,本文主要介绍了Redis实现库存扣减的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2023-07-07
  • redis列表类型_动力节点Java学院整理

    redis列表类型_动力节点Java学院整理

    这篇文章主要为大家详细介绍了redis列表类型的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 浅谈RedisTemplate和StringRedisTemplate的区别

    浅谈RedisTemplate和StringRedisTemplate的区别

    本文主要介绍了RedisTemplate和StringRedisTemplate的区别及个人见解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • Redis安装启动及常见数据类型

    Redis安装启动及常见数据类型

    这篇文章主要介绍了Redis安装启动及常见数据类型,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 虚拟机linux安装redis实现过程解析

    虚拟机linux安装redis实现过程解析

    这篇文章主要介绍了虚拟机linux安装redis实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Redis使用ZSET实现消息队列使用小结

    Redis使用ZSET实现消息队列使用小结

    这篇文章主要介绍了Redis使用ZSET实现消息队列使用总结,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • 一文弄懂Redis单线程和多线程

    一文弄懂Redis单线程和多线程

    本文主要介绍了一文弄懂Redis单线程和多线程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论