乐趣区

关于git:eladmin代码贡献2w人star

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

退出移动版