https://github.com/elunez/eladmin/graphs/contributors id:itdzr
优化点
将用户信息缓存,提升同账户(应用场景:admin)的并发和同一用户多次登录情况下的性能,无需每次登陆都查询数据库,首次查询利用future task(请求数据库作为task,future task作为缓存的value,uid为key)执行异步查询,后续的线程由于缓存key存在会等待首次的查询结果(get方法),减少了数据库资源的消耗。
初始登陆时,因为没有缓存,由于访问数据库资源需要时间,如果不用future,那么当第一个线程未返回结果时,那么缓存仍未有记录,则高并发下第二个线程仍会去访问数据库资源。
分布式缓存尽量用redis,数据量小的的用本地缓存。
缓存选用,考虑redis,concurrentHashmap也可,redis更优,
主要思想
高并发情况下比较消耗资源的计算可以作为future task。避免同时的重复计算。本场景更适合计算场景,无状态的场景。concurrentHashmap可以定时清除。
代码
concurrentHashmap<uid/uname,Future<udto>> userDtoCache;
Future<JwtUserDto> future=userDtoCache.get(uid);
if ( future!=null) {
try {
jwtUserDto=future.get();
}catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 检查dataScope是否修改
List<Long> dataScopes = jwtUserDto.getDataScopes();
dataScopes.clear();
dataScopes.addAll(dataService.getDeptIds(jwtUserDto.getUser()));
}else{
Callable<JwtUserDto> call=()->getJwtBySearchDB(username);
FutureTask<JwtUserDto> ft=new FutureTask<>(call);
future=userDtoCache.putIfAbsent(username,ft);
if(future==null){
future=ft;
executor.submit(ft);
}
try{
return future.get();
}catch(CancellationException e){
userDtoCache.remove(username);
}catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return jwtUserDto;
putIfAbsent 如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。