Redis 缓存数据库查询的实现

Redis 缓存数据库查询的实现

1. 需求背景

  • 数据库表 globalship 存储大量船舶信息,每次查询船舶信息时,使用 mmsi 作为查询条件。
  • 由于数据量大,直接查询数据库性能较差,计划引入 Redis 缓存优化查询速度。
  • 目标:通过 mmsi 查询船舶信息,若 Redis 中存在缓存则直接返回,否则查询数据库,并将结果缓存到 Redis。

2. 实现思路

  1. 先查询 Redis 缓存:根据 mmsi 在 Redis 中查找船舶信息。如果找到,直接返回缓存结果。
  2. 查询数据库:如果 Redis 中没有对应的缓存,则查询数据库,获取船舶信息。
  3. 缓存结果到 Redis:将数据库查询的结果写入 Redis,并设置缓存的过期时间,防止数据长期占用 Redis 内存。
  4. 返回结果:返回缓存或数据库查询的结果。

3. Redis 缓存代码实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
public class GlobalShipService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private GlobalShipRepository globalShipRepository; // 假设这是数据库操作接口

    private static final String REDIS_PREFIX = "globalship:"; // Redis 键的前缀
    private static final long CACHE_EXPIRATION = 1; // 缓存过期时间,单位:小时

    public GlobalShip getShipByMmsi(Long mmsi) {
        String redisKey = REDIS_PREFIX + mmsi;
        
        // 1. 查询 Redis 缓存
        GlobalShip globalShip = (GlobalShip) redisTemplate.opsForValue().get(redisKey);
        
        if (globalShip != null) {
            // 缓存命中,直接返回
            return globalShip;
        }
        
        // 2. 如果缓存没有命中,查询数据库
        globalShip = globalShipRepository.findByMmsi(mmsi);
        
        if (globalShip != null) {
            // 3. 数据库查询结果缓存到 Redis,设置缓存过期时间
            redisTemplate.opsForValue().set(redisKey, globalShip, CACHE_EXPIRATION, TimeUnit.HOURS);
        }
        
        // 4. 返回结果(缓存或数据库查询结果)
        return globalShip;
    }
}

4. 代码实现关键点

  • Redis 缓存查询redisTemplate.opsForValue().get(redisKey),根据 mmsi 查询 Redis。
  • 数据库查询globalShipRepository.findByMmsi(mmsi),当 Redis 中没有数据时,查询数据库。
  • 缓存写入redisTemplate.opsForValue().set(redisKey, globalShip, CACHE_EXPIRATION, TimeUnit.HOURS),将数据库查询结果写入 Redis,设置 1 小时的缓存过期时间。

5. 优化措施

  • 防止缓存穿透:如果数据库查询结果为空,可以缓存一个标志,防止重复查询同样的无效数据。例如,缓存空对象或特定标志。
if (globalShip == null) {
    redisTemplate.opsForValue().set(redisKey, "NOT_FOUND", CACHE_EXPIRATION, TimeUnit.HOURS);
}
  • 缓存雪崩防护:给不同的缓存键设置随机过期时间,避免大量缓存同时过期,导致 Redis 负载过高。
long expirationTime = CACHE_EXPIRATION + new Random().nextInt(30); // 随机过期时间,1小时到1小时30分钟
redisTemplate.opsForValue().set(redisKey, globalShip, expirationTime, TimeUnit.HOURS);
  • 批量查询和缓存:如果可以,尽量减少单条查询和缓存,使用批量查询和缓存的方式,提高性能。

6. 注意事项

  • 缓存更新策略:当数据库中的数据发生变化时,需要更新 Redis 中的缓存,可以采用写操作后清除对应缓存或定时刷新缓存的机制。
  • 缓存大小控制:要注意控制 Redis 的内存使用,设置合理的过期时间和内存淘汰策略,防止 Redis 被大量缓存数据占用。

7. 适用场景

  • 适用于数据量大、查询频繁但数据变化不频繁的场景,如船舶信息、商品信息等场景。
posted @   槑孒  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示