(1) 修改 com.atguigu.gulimall.product.service.impl.CategoryServiceImpl 的 getCatalogJson 方法
//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 = getCatalogJsonFromDb(); System.out.println("缓存不命中....将要查询数据库...."); return catalogJsonFromDb; } System.out.println("缓存命中....直接返回....."); //转为我们指定的对象 Map> result = JSON.parseObject(catalogJson, new TypeReference
锁时序问题:之前的逻辑是查缓存没有,然后取竞争锁查数据库,这样就造成多 次查数据库。 解决方法:竞争到锁后,再次确认缓存中没有,再去查数据库。(2)jemeter 测试 100的并发 查看是否锁住,是否只查询了一次数据库 测试结果:
确认只查了一次,确实锁住了