在使用redis作为缓存中间件时,在高并发的情况下,会出现缓存失效的问题。
缓存穿透、缓存雪崩、缓存击穿。
对于缓存穿透我们可以使用锁来解决。本文讲如何使用本地锁来解决穿透问题。只适用于单体应用。
主业务方法:
@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_JSONString(categorysJsonFromDB),1, TimeUnit.DAYS);return categorysJsonFromDB;}
解决缓存击穿问题
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_JSONString(datasFromDB),1, TimeUnit.DAYS);return datasFromDB;}Map<Long, List<Category2Level>> longListMap = JSON.parseObject(s, new TypeReference<Map<Long, List<Category2Level>>>() {});return longListMap;}}
缺点:如果在每个机器上都部署,每个this都是一把锁,几台机器就有几个实例对象,想要锁住所有,必须使用分布式锁
本文发布于:2024-02-04 22:53:06,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170718220260469.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |