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


信静
1 声望0 粉丝

404 NOT FOUND