什么是/使用缓存(Cache),缓存更新策略数据库缓存不一致解决方案 及 实现缓存与数据库双写一致
Posted Perceus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是/使用缓存(Cache),缓存更新策略数据库缓存不一致解决方案 及 实现缓存与数据库双写一致相关的知识,希望对你有一定的参考价值。
(目录)
实现这个方案:商户查询缓存
商户查询缓存
1. 什么是缓存 ( Cache )?
前言:什么是缓存?
举个例子:
例如:
例1:Static final ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>();
例2:static final Cache<K,V> USER_CACHE = CacheBuilder.newBuilder().build();
例3:Static final Map<K,V> map = new HashMap();
为什么要使用缓存
但是缓存也会增加代码复杂度和运营的成本:
如何使用缓存
实际开发中,会构筑多级缓存
来使系统运行速度进一步提升。
例如:本地缓存
与 redis中的缓存并发使用
2. 添加 商户缓存、商铺分类缓存
@GetMapping("/id")
public Result queryShopById(@PathVariable("id") Long id)
//这里是直接查询数据库
return shopService.queryById(id);
缓存模型和思路
标准操作方式:
添加商户缓存代码:
代码思路:
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Result queryShopById(Long id)
// 1. 从 Redis 中查询商铺缓存
String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
// 2. 判断是否存在
// 3. 存在 , 直接返回
if(StrUtil.isNotBlank(shopJson))
Shop shop=JSONUtil.toBean(shopJson, Shop.class);
return Result.ok(shop);
// 4. 不存在 ,根据 id 去数据库查询
Shop shop = getById(id);
// 5. 不存在 , 返回 404
if(shop==null)
return Result.fail("商铺不存在");
// 6. 存在 , 写入 Redis
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop));
return Result.ok(shop);
添加商铺分类缓存:
package com.hmdp.controller;
import com.hmdp.dto.Result;
import com.hmdp.entity.ShopType;
import com.hmdp.service.IShopTypeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/shop-type")
public class ShopTypeController
@Resource
private IShopTypeService typeService;
// public Result queryTypeList()
// List<ShopType> typeList = typeService
// .query().orderByAsc("sort").list();
// return Result.ok(typeList);
//
@GetMapping("list")
public Result queryTypeList()
return typeService.queryTypeLists();
package com.hmdp.service;
import com.hmdp.dto.Result;
import com.hmdp.entity.ShopType;
import com.baomidou.mybatisplus.extension.service.IService;
public interface IShopTypeService extends IService<ShopType>
Result queryTypeLists();
package com.hmdp.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.ShopType;
import com.hmdp.mapper.ShopTypeMapper;
import com.hmdp.service.IShopTypeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisConstants;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class ShopTypeServiceImpl extends ServiceImpl<ShopTypeMapper, ShopType> implements IShopTypeService
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public Result queryTypeLists()
//获取radis中商户
String shopType=stringRedisTemplate.opsForValue().get("shopType");
if (StrUtil.isNotBlank(shopType))
//存在,直接返回
List<ShopType> shopTypes = JSONUtil.toList(shopType, ShopType.class);
return Result.ok(shopTypes);
//不存在,从数据库中查询写入redis
List<ShopType> shopTypes = query().orderByAsc("sort").list();
//不存在,返回错误
if (shopTypes == null)
return Result.fail("分类不存在");
//将查询到的信息存入radis
stringRedisTemplate.opsForValue().set("shopType",JSONUtil.toJsonStr(shopTypes));
//返回
return Result.ok(shopTypes);
效果展示:
没添加缓存前:耗时 1.54s
添加缓存后:254ms
3. 缓存更新策略
缓存更新
是redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵
,当我们向redis插入太多数据。
此时就可能会导致缓存中的数据过多
,所以redis会对部分数据进行更新,或者把他叫为淘汰
更合适。
数据库缓存不一致解决方案:
有如下几种方案:
数据库和缓存不一致采用什么方案
综合考虑使用方案一,但是方案一调用者如何处理呢?这里有几个问题
操作缓存和数据库时有三个问题需要考虑:
- 删除缓存还是更新缓存?
- 如何保证缓存与数据库的操作的同时成功或失败?
- 先操作缓存还是先操作数据库?
因为缓存操作极快,方案二出现问题可能性低
4. 实现商铺和缓存与数据库双写一致
核心思路如下:
修改ShopController中的业务逻辑,满足下面的需求
:
修改重点代码1
:修改ShopServiceImpl的queryById方法
修改重点代码2
代码分析:
/**
* 查询商铺
* @param id
* @return
*/
@Override
public Result queryShopById(Long id)
// 1. 从 Redis 中查询商铺缓存
String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
// 2. 判断是否存在
// 3. 存在 , 直接返回
if(StrUtil.isNotBlank(shopJson))
Shop shop=JSONUtil.toBean(shopJson, Shop.class);
return Result.ok(shop);
// 4. 不存在 ,根据 id 去数据库查询
Shop shop = getById(id);
// 5. 不存在 , 返回 404
if(shop==null)
return Result.fail("商铺不存在");
// 6. 存在 , 写入 Redis
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);
return Result.ok(shop);
以上是关于什么是/使用缓存(Cache),缓存更新策略数据库缓存不一致解决方案 及 实现缓存与数据库双写一致的主要内容,如果未能解决你的问题,请参考以下文章