基于Redis提高查询性能(保持数据一致性)

Redis实战篇 | Kyle's Blog (cyborg2077.github.io)

目录

背景

商户查询缓存(根据ID查询)

 根据店铺类型查询(List型)

缓存更新策略(保证数据一致性)

案例(利用缓存更新策略)


背景

起初客户端直接向数据库查询数据                              添加redis后 

商户查询缓存(根据ID查询)

 实现业务流程

 ShopController

    @GetMapping("/{id}")
    public Result queryShopById(@PathVariable("id") Long id) {
        return shopService.queryById(id);
    }

IShopService 

public interface IShopService extends IService<Shop> {

    Result queryById(Long id);
}

ShopServiceImpl 

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
    @Resource
    public StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryById(Long id) {
        String key = CACHE_SHOP_KEY + id;
        // 1.从redis查询商铺缓存
        String shopJson = stringRedisTemplate.opsForValue().get(key);
        // 2.判断缓存是否命中
        if(StrUtil.isNotBlank(shopJson)){
            // 3.缓存命中,返回
            // 将json反序列化为对象
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }
        // 4.缓存未命中,根据id查询数据库
        Shop shop = getById(id);
        // 5.数据库不存在,返回错误
        if(shop == null){
            return Result.fail("店铺不存在");
        }
        // 6.数据库存在,写入缓存
        stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),30L, TimeUnit.MINUTES);
        // 7.返回
        return Result.ok(shop);
    }
}

 根据店铺类型查询(List型)

Controller 

@RestController
@RequestMapping("/shop-type")
public class ShopTypeController {
    @Resource
    private IShopTypeService typeService;

    @GetMapping("list")
    public Result queryTypeList() {
        return typeService.queryList();
    }
}

接口 

public interface IShopTypeService extends IService<ShopType> {
    Result queryList();
}

实现类

@Service
public class ShopTypeServiceImpl extends ServiceImpl<ShopTypeMapper, ShopType> implements IShopTypeService {
    @Resource
    public StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryList() {
        // 1.从redis查询商铺类型
        List<String> shopTypes = stringRedisTemplate.opsForList().range(CACHE_SHOP_KEY, 0, -1);
        // 2.判断redis是否命中
        if(!shopTypes.isEmpty()){
            //如果命中则转为ShopType类型返回
            List<ShopType> tmp = new ArrayList<>();
            for (String types : shopTypes) {
                ShopType shopType = JSONUtil.toBean(types, ShopType.class);
                tmp.add(shopType);
            }
            return Result.ok(tmp);
        }
        //没有命中则查询数据库
        List<ShopType> tmp = query().orderByAsc("sort").list();
        if(tmp.isEmpty()){
            return Result.fail("店铺类型不存在");
        }
        //3.将数据写入redis
        shopTypes.forEach(shopType -> {
            stringRedisTemplate.opsForList().rightPush(CACHE_SHOP_KEY,JSONUtil.toJsonStr(shopType));
        });
        //4.返回
        return Result.ok(tmp);
    }
}

缓存更新策略(保证数据一致性)

 三种更新缓存的策略(保证数据一致性)

我们主要使用主动更新策略

又因为操作数据库和缓存的先后顺序,线程问题;因此需要先修改数据库,再删除缓存,加锁,使用事务。

案例(利用缓存更新策略)

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

// 6.数据库存在,写入缓存
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL , TimeUnit.MINUTES);

根据id修改店铺时,先修改数据库,再删除缓存

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

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值