谷粒商城分布式高级(七)

您所在的位置:网站首页 分布式锁的实际原则包括 谷粒商城分布式高级(七)

谷粒商城分布式高级(七)

2024-07-12 00:47| 来源: 网络整理| 查看: 265

//TODO 产生堆外内存溢出:OutOfDirectMemoryError//(1)springboot2.0以后默认使用lettuce作为操作redis客户端。它使用netty进行网络通信//(2)lettuce的bug导致netty堆外内存溢出 -Xmx300m;netty如果没有指定堆外内存,默认使用-Xmx300m// 可以通过-Dio.netty.maxDirectMemory进行设置// 解决方案:不能使用-Dio.netty.maxDirectMemory只去调大堆外内存。//(1)升级lettuce客户端//(2)切换使用jedis@Overridepublic Map getCatalogJson() { //给缓存中放json字符串,拿出的json字符串,还要逆转为能用的对象类型:【序列化与反序列化】

/** * 1、空结果缓存:解决缓存穿透 * 2、设置过期时间(加随机值):解决缓存雪崩 * 3、枷锁:解决缓存击穿 */

//1、加入缓存逻辑,缓存中存的数据是json字符串 //JSO跨语言、跨平台兼容 String catalogJson = redisTemplate.opsForValue().get("catalogJson"); if(StringUtils.isEmpty(catalogJson)){ //2、缓存中没有,查询数据库 Map catalogJsonFromDb = getCatalogJsonFromDbWithRedisLock(); System.out.println("缓存不命中....将要查询数据库...."); return catalogJsonFromDb; } System.out.println("缓存命中....直接返回....."); //转为我们指定的对象 Map result = JSON.parseObject(catalogJson, new TypeReference(){}); return result;}

public Map getCatalogJsonFromDbWithRedisLock() { //1、占分布式锁,去redis占坑 String uuid = UUID.randomUUID().toString(); Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock",uuid,300,TimeUnit.SECONDS); if(lock){ System.out.println("获取分布式锁成功....."); //加锁成功....执行业务 //2、设置过期时间,必须和加锁是同步的,原子的 //redisTemplate.expire("lock",30,TimeUnit.SECONDS); Map dataFromDB; try{ dataFromDB = getDataFromDB(); }finally { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; //删除锁 Integer lock1 = redisTemplate.execute(new DefaultRedisScript(script, Integer.class) , Arrays.asList("lock"), uuid); }

//获取值对比+对比成功删除=原子操作 lua脚本解锁 /*String lockValue = redisTemplate.opsForValue().get("lock"); if(uuid.equals(lockValue)){ //删除自己的锁 redisTemplate.delete("lock");//删除锁 }*/

return dataFromDB; }else{ //加锁失败....重试。synchronized //休眠100ms重试 System.out.println("获取分布式锁失败,等待重试....."); try { Thread.sleep(200); }catch (Exception e){ e.printStackTrace(); } return getCatalogJsonFromDbWithRedisLock();//自旋的方式 }}

private Map getDataFromDB() { String catalogJson = redisTemplate.opsForValue().get("catalogJson"); if(!StringUtils.isEmpty(catalogJson)){ //缓存不为null直接返回 Map result = JSON.parseObject(catalogJson, new TypeReference(){}); return result; }

System.out.println("查询了数据库.....");

/** * 1、将数据库的多次查询变为一次 */ List selectList = baseMapper.selectList(null);

//1、查询所有一级分类 List level1Catagorys = getParent_cid(selectList, 0L);

//2、封装数据 Map parent_cid = level1Catagorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> { // 1、每一个的一级分类,查到这个以及分类的二级分类 List categoryEntities = getParent_cid(selectList, v.getCatId()); //2、封装上面的结果 List catelog2Vos = null; if (categoryEntities != null) { catelog2Vos = categoryEntities.stream().map(l2 -> { Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName()); //1、找当前二级分类的三级分类封装成vo List level3Catalog = getParent_cid(selectList, l2.getCatId()); if(level3Catalog!=null){ List collect = level3Catalog.stream().map(l3 -> { //2、封装成指定格式 Catelog2Vo.Category3Vo category3Vo = new Catelog2Vo.Category3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName()); return category3Vo; }).collect(Collectors.toList()); catelog2Vo.setCatalog3List(collect); } return catelog2Vo; }).collect(Collectors.toList()); } return catelog2Vos; }));

//3、查到的数据再放入缓存,将对象转为json放到缓存中 String s = JSON.toJSONString(parent_cid); redisTemplate.opsForValue().set("catalogJson", s, 1, TimeUnit.DAYS);

return parent_cid;}



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3