点评项目-5-商户查询缓存,从 2s 优化到 12ms

业务需求:当前端发送 shop/id 的请求时,我们需要向前端响应对应 id 的详细数据给前端

直接查询 mysql 效率比较低,我们可以使用 redis 作为中间件进行数据的缓存,先查询 redis ,若redis 中未查询到,则在 mysql 中查询,并在查询后写入 redis 中

第一步,Controller

java 复制代码
@RestController
@RequestMapping("/shop")
public class ShopController {
    
    @Resource
    public ShopService shopService;
    
    //接收携带店铺id的请求,响应店铺信息
    @GetMapping("/{id}")
    public Result queryShopById(@PathVariable("id") Long id){
        return shopService.getById(id);
    }
    
}

实现店铺信息的封装 Pojo 类

java 复制代码
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_shop")
public class Shop implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 商铺名称
     */
    private String name;

    /**
     * 商铺类型的id
     */
    private Long typeId;

    /**
     * 商铺图片,多个图片以','隔开
     */
    private String images;

    /**
     * 商圈,例如陆家嘴
     */
    private String area;

    /**
     * 地址
     */
    private String address;

    /**
     * 经度
     */
    private Double x;

    /**
     * 维度
     */
    private Double y;

    /**
     * 均价,取整数
     */
    private Long avgPrice;

    /**
     * 销量
     */
    private Integer sold;

    /**
     * 评论数量
     */
    private Integer comments;

    /**
     * 评分,1~5分,乘10保存,避免小数
     */
    private Integer score;

    /**
     * 营业时间,例如 10:00-22:00
     */
    private String openHours;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;


    @TableField(exist = false)
    private Double distance;
}

第二步,Service 及其实现类

java 复制代码
public interface ShopService {
    Result getById(Long id);
}
java 复制代码
@Service
public class ShopServiceImpl implements ShopService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ShopMapper shopMapper;

    @Override
    public Result getById(Long id) {
        //先在 redis 中查询
        String shopJson = stringRedisTemplate.opsForValue().get("cache:shop:" + id);
        if(StrUtil.isNotBlank(shopJson)){
            return Result.ok(JSONUtil.toBean(shopJson,Shop.class));
        }
        //redis 中没有,在 mysql 中查询
        Shop shop = shopMapper.selectById(id);
        if(shop == null){
            //mysql 中也没有,返回未查询到
            return Result.fail("未查询到该店铺ToT");
        }
        //查到了,将查询到的数据写入 redis
        stringRedisTemplate.opsForValue().set("cache:shop:" + id,JSONUtil.toJsonStr(shop));
        return Result.ok(shop);
    }
}

最后一步,将店铺查询的拦截放开,进行测试

java 复制代码
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加更新 token 拦截器,默认先添加先拦截,也可以通过.order() 来设置拦截的先后顺序
        registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate));
        //添加判断是否登录的拦截器
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns("/user/code", "/user/login","/shop/**");
    }

第一次访问时耗时两秒多,存入 redis 缓存后,第二次查询效率显著提升,从 2s 优化到了 12ms

相关推荐
千宇宙航6 小时前
闲庭信步使用图像验证平台加速FPGA的开发:第九课——图像插值的FPGA实现
图像处理·计算机视觉·缓存·fpga开发
全栈凯哥7 小时前
20.缓存问题与解决方案详解教程
java·spring boot·redis·后端·缓存
Hellyc14 小时前
用户查询优惠券之缓存击穿
java·redis·缓存
鼠鼠我捏,要死了捏16 小时前
缓存穿透与击穿多方案对比与实践指南
redis·缓存·实践指南
汤姆大聪明1 天前
Redis 持久化机制
数据库·redis·缓存
kk在加油1 天前
Redis数据安全性分析
数据库·redis·缓存
hcvinh2 天前
CANDENCE 17.4 进行元器件缓存更新
学习·缓存
墨着染霜华2 天前
Caffeine的tokenCache与Spring的CaffeineCacheManager缓存区别
java·spring·缓存
weixin_438335402 天前
Redis:分组与设备在 Redis 中缓存存储设计
redis·缓存·bootstrap
秋也凉2 天前
redis的命令集合
数据库·redis·缓存