技术经验高并发总结第一篇
2022/08/24
本文于
869
天之前发表,文中内容可能已经过时。
FutureTask的使用
场景一
我这边需要提供一个接口给客户端,这个接口需要请求外部接口20次,在这种场景下,我需要如何设计我的这个接口?
解决方案java篇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| List<FutureTask<List<String>>> tasks=new ArrayList<>(10); for(int i=0;i<repeat;i++){ FutureTask<List<String>> futureTask = new FutureTask<>(() -> mobileComponent.getMobileList(numProvinceCode, numCityCode, req.getSearchValue())); threadPoolTaskExecutor.execute(futureTask); tasks.add(futureTask); } tasks.forEach(task->{ try { mobileList.addAll(task.get()); } catch (InterruptedException e) { log.error("获取手机号码 失败,请求串= {}", JSON.toJSONString(req),e); } catch (ExecutionException e) { log.error("获取手机号码 失败 = {}", JSON.toJSONString(req),e); } });
|
长短缓存的使用
场景一
在高并发场景中,如何防止缓存穿透的问题,如果没想清楚的情况下,可能认为加锁就能解决问题了,但在锁失效的情况下,其实还是没办法保证有多少的线程在锁失效的情况下落到了db里面,这就是一个考验运气的问题.,所以需要用到长短缓存去既能保证数据更新的实时性,又能保证不管在如何的高并发下,落到db的查询永远只有一条,这才能真正解决缓存穿透导致雪崩的问题.
解决方案java篇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public boolean isBlack(Long cardId, Integer areaCode) { String shortKey = "cache_card_black_short_" + cardId; String longKey = "cache_card_black_long_" + cardId; List<Integer> areaCodes; if (redisTemplate.hasKey(shortKey)) { //先从短缓存里面获取数据 areaCodes = (List<Integer>) redisTemplate.opsForValue().get(shortKey); } else { Lock lock = redisson.getLock(LockPrefix.CARD_BLACK_AREA + cardId); //如果获取到锁,从数据库里面获取数据,放到长短缓存里面 if (lock.tryLock()) { try { areaCodes = refresh(cardId, shortKey, longKey); } finally { lock.unlock(); } } else { if (redisTemplate.hasKey(longKey)) { areaCodes = (List<Integer>) redisTemplate.opsForValue().get(longKey); } else { Lock longLock = redisson.getLock(LockPrefix.CARD_BLACK_AREA_LONG + cardId); try { longLock.lock(); areaCodes = refresh(cardId, shortKey, longKey); } finally { longLock.unlock(); } }
} } return areaCodes.contains(areaCode); }
private List<Integer> refresh(Long cardId, String shortKey, String longKey) { List<CardBlackArea> blackAreas = this.baseMapper.lambdaQuery().eq(CardBlackArea::getCardId, cardId).list(); List<Integer> areaCodes = blackAreas.stream().map(a -> a.getAreaCode()).collect(Collectors.toList()); redisTemplate.opsForValue().set(shortKey, areaCodes, 5, TimeUnit.MINUTES); redisTemplate.opsForValue().set(longKey, areaCodes, 1, TimeUnit.DAYS); return areaCodes; }
|