【redis商户缓存】redis商户缓存

redis商户缓存

越野车,山地自行车,都拥有"避震器",防止车体加速后因惯性,在酷似"U"字母的地形上飞跃,硬着陆导致的损害,像个弹簧一样;

同样,实际开发中,系统也需要"避震器",防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪;

这在实际开发中对企业讲,对产品口碑,用户评价都是致命的;所以企业非常重视缓存技术;

1:Static final ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>(); 本地用于高并发

例2:static final Cache<K,V> USER_CACHE = CacheBuilder.newBuilder().build(); 用于redis等缓存

例3:Static final Map<K,V> map =  new HashMap(); 本地缓存

由于其被Static修饰,所以随着类的加载而被加载到内存之中,作为本地缓存,由于其又被final修饰,所以其引用(例3:map)和对象(例3:new HashMap())之间的关系是固定的,不能改变,因此不用担心赋值(=)导致缓存失效;

一、为什么要使用缓存

一句话:因为速度快,好用

缓存数据存储于代码中,而代码运行在内存中,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力

实际开发过程中,企业的数据量,少则几十万,多则几千万,这么大数据量,如果没有缓存来作为"避震器",系统是几乎撑不住的,所以企业会大量运用到缓存技术;

但是缓存也会增加代码复杂度和运营的成本。

二、如何使用缓存

实际开发中,会构筑多级缓存来使系统运行速度进一步提升,例如:本地缓存与redis中的缓存并发使用

浏览器缓存:主要是存在于浏览器端的缓存

应用层缓存: 可以分为tomcat本地缓存,比如之前提到的map,或者是使用redis作为缓存

数据库缓存: 在数据库中有一片空间是 buffer pool,增改查数据都会先加载到mysql的缓存中

CPU缓存: 当代计算机最大的问题是 cpu性能提升了,但内存读写速度没有跟上,所以为了适应当下的情况,增加了cpu的L1,L2,L3级的缓存

在这里插入图片描述

三、案例使用缓存

添加商户缓存
在我们查询商户信息时,我们是直接操作从数据库中去进行查询的,大致逻辑是这样,直接查询数据库那肯定慢咯,所以我们需要增加缓存

@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {
    //这里是直接查询数据库
    return shopService.queryById(id);
}

1. 缓存模型和思路

标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。
在这里插入图片描述

2. 查询店铺

根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result getByIdShop(Long id) {
        //查询redis中是否有值,有则直接返回
        String key = CACHE_SHOP_KEY + id;
        String cacheShop = stringRedisTemplate.opsForValue().get(key);
        if (ObjectUtil.isNotEmpty(cacheShop)) {
            Shop shopBean = JSONUtil.toBean(cacheShop, Shop.class);
            return Result.ok(shopBean);
        }
        //没有,查询数据库
        Shop shop = getById(id);
        //判断查询的店铺是否为空
        if (shop == null) {
            return Result.fail("店铺不存在");
        }
        //将对象转为json字符串
        String jsonShop = JSONUtil.toJsonStr(shop);
        //放进redis
        stringRedisTemplate.opsForValue().set(key,jsonShop);
        //设置超时时间
        stringRedisTemplate.expire(key,CACHE_SHOP_TTL, TimeUnit.MINUTES);
        return Result.ok(shop);
    }
}

3. 修改店铺信息

分析:修改店铺时,应先修改数据库,再删除redis缓存,这样能最小化出现缓存和数据库不一致的情况。

如果为先删除缓存再修改数据库的话,删除缓存比较快,几乎是毫秒级的(毕竟redis以速度快而闻名嘛),而修改数据库就相对比较慢了,这时如果有另外一个线程查询这条数据,而redis中的值刚被干掉,就会将查询出的结果又存入redis,所以就出现了缓存与数据库不一致的情况。


而先修改数据库的再删除缓存的话,就能降低上面的巧合,但不能完全避免。

在这里插入图片描述

我们确定了采用删除策略,来解决双写问题,当我们修改了数据之后,然后把缓存中的数据进行删除,查询时发现缓存中没有数据,则会从mysql中加载最新的数据,从而避免数据库和缓存不一致的问题

分析完之后,写代码时十分简单:

    @Override
    @Transactional
    public Result update(Shop shop) {
        Long id = shop.getId();
        if (id == null) {
            Result.fail("店铺ID不能为空");
        }
        // 更新数据库
        boolean b = updateById(shop);
        if (b){
            //删除缓存
            stringRedisTemplate.delete(CACHE_SHOP_KEY + id);
            return Result.ok();
        }
        // 更新失败
        return Result.fail("操作失败");
    }

@Transactional: 事务,标记的代码要么全成功,要么全失败。失败了会回滚已经操作过的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打乒乓球只会抽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值