redis的本地锁的使用

redis 的问题

在使用redis作为缓存中间件时,在高并发的情况下,会出现缓存失效的问题。
缓存穿透、缓存雪崩、缓存击穿。

缓存穿透

在这里插入图片描述

缓存雪崩

在这里插入图片描述

缓存击穿

在这里插入图片描述

本地锁

对于缓存穿透我们可以使用锁来解决。本文讲如何使用本地锁来解决穿透问题。只适用于单体应用。

synchronized

主业务方法:

@Autowired
private StringRedisTemplate redisTemplate;

private final static String CATEGORY_JSON_KEY = "category_json_key";
public Map<Long,List<Category2Level>> getCategorysJson() {
		// 先从redis缓存中查询是否有该数据
        String s = redisTemplate.opsForValue().get(CATEGORY_JSON_KEY);
        // 有缓存
        if (!StringUtils.isEmpty(s)){
            // System.out.println("缓存中有");
            // 字符串转成需要的格式
            Map<Long, List<Category2Level>> longListMap = JSON.parseObject(s, new TypeReference<Map<Long, List<Category2Level>>>() {
            });
            return longListMap;
        }
        // System.out.println("缓存中没有");
        // 在数据库中查询数据
        Map<Long, List<Category2Level>> categorysJsonFromDB = getCategorysJsonFromDB();
        // 没有添加锁之前不用去掉注释,在获取数据后直接保存到redis
        // 在redis缓存中存数据 在锁结束时保存到缓存中
        // redisTemplate.opsForValue().set(CATEGORY_JSON_KEY,JSON.toJSONString(categorysJsonFromDB),1, TimeUnit.DAYS);
        return categorysJsonFromDB;
    }

解决缓存击穿问题

  1. 只要是同一把锁,就能锁住需要这个锁的所有线程
  2. synchronized(this),springboot所有的组件在容器中都是单例的
  3. 得到锁之后,我们应该再去缓存中确定一次,如果没有才需要继续查询
private Map<Long,List<Category2Level>> getCategorysJsonFromDB() {
        synchronized (this){
        	// 当其他的线程进来的时候直接查询缓存,避免操作数据库 
            String s = redisTemplate.opsForValue().get(CATEGORY_JSON_KEY);
            // 缓存中没有
            if (StringUtils.isEmpty(s)){
                // System.out.println("查询数据库"); getDatasFromDB();是业务逻辑
                Map<Long, List<Category2Level>> datasFromDB = getDatasFromDB();
                // 在redis缓存中存数据 在锁结束时保存到缓存中
                redisTemplate.opsForValue().set(CATEGORY_JSON_KEY,JSON.toJSONString(datasFromDB),1, TimeUnit.DAYS);
                return datasFromDB;
            }
            Map<Long, List<Category2Level>> longListMap = JSON.parseObject(s, new TypeReference<Map<Long, List<Category2Level>>>() {
            });
            return longListMap;
        }
    }

缺点:如果在每个机器上都部署,每个this都是一把锁,几台机器就有几个实例对象,想要锁住所有,必须使用分布式锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值