• 33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)


    说明:

    (1)声明:这个其中的区别和相同点,要清楚;

              ● 在【32:第三章:开发通行证服务:15:浏览器存储介质,简介;】中,前端使用【把“用户基本信息”存到Session Storage中】来减轻后端接口的压力;;;;这是,从前端的角度出发,来减轻后端接口的压力;

              ● 本篇博客,使用Redis缓存用户信息,是利用Redis来减轻访问数据库的压力;

              ● 这两篇博客的内容,其目的差不多,都是降低系统压力,提高并发量;;;;但是,其着力点和具体做法存在差异的;

    (2)以前在【Spring Boot电商项目31:商品分类模块十:利用Redis缓存加速响应;】、【附加:【Spring Boot缓存】【Redis】;】介绍过在利用Redis缓存的案例;虽然和本篇博客在技术上存在差异,但其目的是差不多的;有点条条大路通罗马的感觉;

    目录

    零:本篇博客合理性说明; 

    1.问题阐述;

    2.使用redis缓存用户信息,减轻数据库压力:简介; 

    一:使用redis缓存用户信息,以减轻数据库的压力;

    1.修改getUser()方法的逻辑:redis中有用户信息,就从redis中拿;redis中没有用户信息,就从数据库中查,同时把查到的用户信息存到redis中去;

    2.当调用【修改/完善用户信息,接口】修改了用户信息后,我们也要及时的去更新redis中的用户信息;

    二:效果;

    step1:第一次注册/登录用户;

    step2:去更新/完善用户信息;

    一个前端的、未解决的问题;

    step3:Redis缓存效果演示;


    零:本篇博客合理性说明; 

    1.问题阐述;

    (1)我们在【32:第三章:开发通行证服务:15:浏览器存储介质,简介;】中,已经介绍了浏览器存储介质,其中在针对【获得用户基本信息,接口】,在前端使用了Session Storage这个存储介质;;;当时的逻辑是:

              ● 前端第一次想要获取“用户基本信息”的时候,其会去调用后端的【获得用户基本信息,接口】接口;

              ● 同时,我们在前端代码中编写了对应的代码,把获得的“用户基本信息”存储到了Session Storage中;

              ● 后面,当前端第二次想要获取“用户基本信息”的时候,其就不会去调用后端的【获得用户基本信息,接口】接口了,而是从Session Storage中获取;


    (2)上面我们在前端的角度,利用了Session Storage的手段,去减轻了接口的压力;提高了系统的抗并发能力;

    (3)同时,我们也可以从后端的角度出发;;;利用Redis缓存用户信息数据,来减轻数据库的压力,从而提高系统的抗并发能力;

    (4)PS:使用Session Storage存储用户基本信息时的一个问题:用户在第一次请求的时候,数据存在了Session Storage中;;;但是用户如果更改了信息,而此时由于浏览器中有Session Storage,那么此时用户再去获取信息的时候,获取的就是一些过时的数据了:PS:虽然自己对前端代码不太了解,但是经过实测,每次我们更新信息后,前端都会清除掉在Session Storage存放的旧的用户信息;

    2.使用redis缓存用户信息,减轻数据库压力:简介; 

    (1)原本,每次当我们需要调用【获得用户账户信息,接口】和【获得用户基本信息,接口】的时候,都是需要去访问数据库的;;;但是,如果我们把完整的用户信息缓存到Redis中;;;那么,再需要调用【获得用户账户信息,接口】和【获得用户基本信息,接口】以获得用户信息的时候,其就可以从redsi中拿,而不用再从数据库中取了;


    一:使用redis缓存用户信息,以减轻数据库的压力;

    1.修改getUser()方法的逻辑:redis中有用户信息,就从redis中拿;redis中没有用户信息,就从数据库中查,同时把查到的用户信息存到redis中去;

    修改我们在【user】用户微服务中的、UserController中定义的、根据userId去查user的,getUser()方法的逻辑;

    1. /**
    2. * 公用方法:根据userId去查user;
    3. * @param userId
    4. * @return
    5. */
    6. private AppUser getUser(String userId) {
    7. // 说明:由于“用户信息”不太常会变动;对于一些千万级别的网站来说,当某个用户第一次查询用户信息的时候,
    8. // 这些信息我们完全可以使用redis缓存起来;这样一来,用户后续再获取信息的时候,就可以从redis中
    9. // 获取,就不用查询数据库了;
    10. AppUser user = null;
    11. //(1)去redis中查一查,看redis中是否已经有了这个用户的用户信息;
    12. String userJson = redisOperator.get(REDIS_USER_INFO + ":" + userId);
    13. //(2.1)如果redis中,已经有了该用户的信息:那么我们就把JSON中用户信息,转成对应的AppUser对象;
    14. if (StringUtils.isNotBlank(userJson)) {
    15. user = JsonUtils.jsonToPojo(userJson, AppUser.class);
    16. } else {
    17. //(2.2)如果redis中,没有该用户的信息(那么,极大概率是,用户这是第一次来查询用户信息),那么我们
    18. // 就查询数据库,去数据库中获取用户信息;
    19. user = userService.getUser(userId);
    20. //同时,把查到的用户信息,存到redis中去;(以便,让用户在后面第二次想要查询用户信息的时候,就
    21. // 可以直接从redis中拿了,就不用再操作数据库了)
    22. redisOperator.set(REDIS_USER_INFO+":"+userId,JsonUtils.objectToJson(user));
    23. }
    24. //(2.3)返回user用户对象
    25. return user;
    26. }

    说明:

    (1)修改内容;

    (2)逻辑分析;

              ● 看注释;

              ● 因为,我们这儿要操作redis,所以这个类需要注入RedisOperator这个工具类的对象;

              ● 我们在向redis中存用户信息的时候,其key是【redis_user_info:用户id】这种格式;

    2.当调用【修改/完善用户信息,接口】修改了用户信息后,我们也要及时的去更新redis中的用户信息;

    UserServiceImpl中的updataUserInfo()方法;

    1. /**
    2. * 修改/完善用户信息,并且激活用户;
    3. *
    4. * @param updateUserInfoBO
    5. */
    6. @Override
    7. public void updateUserInfo(UpdateUserInfoBO updateUserInfoBO) {
    8. //把前端传过来的updateUserInfoBO中的属性值,copy到一个AppUser对象中去;
    9. AppUser userInfo = new AppUser();
    10. BeanUtils.copyProperties(updateUserInfoBO, userInfo);
    11. //重新设置其更新时间
    12. userInfo.setUpdatedTime(new Date());
    13. //设置其用户状态,把其状态设为1(即已激活);
    14. userInfo.setActiveStatus(UserStatus.ACTIVE.type);
    15. //和mybatis-plus的套路基本一样,我们使用updateByPrimaryKeySelective()方法(这个方法只去更新数据库表中那些userInfo中有的,,没有的不会动);
    16. // 而不使用updateByPrimaryKey();(这个方法会全部更新数据库表的内容,,userInfo没有的,就会设为空了),
    17. int result = appUserMapper.updateByPrimaryKeySelective(userInfo);
    18. if (result != 1) {//如果上面方法的返回值不为1,就表示这个更新操作出了问题,那么我们就抛出一个异常;
    19. GraceException.display(ResponseStatusEnum.USER_UPDATE_ERROR);
    20. }
    21. //能走到这一步,说明用户信息更新是OK的;那么,此时我们去获取最新的用户信息,把其存到redis中去;
    22. String userId = updateUserInfoBO.getId();
    23. AppUser user = getUser(userId);
    24. redisOperator.set(REDIS_USER_INFO+":"+userId, JsonUtils.objectToJson(user));//这个会覆盖掉旧值
    25. }

    说明: 

    (1)修改内容;

              ● 因为,我们这儿要操作redis,所以这个类需要注入RedisOperator这个工具类的对象;同时,我们在向redis中存用户信息的时候,其key的格式,需要按照【redis_user_info:用户id】这种格式;


    二:效果;

    先全局install一下整个项目,然后启动【user】用户微服务的主启动了;

    同时,为了防止任何干扰,我们清除了浏览器缓存、数据库数据、redis中数据;

    step1:第一次注册/登录用户;

    我们第一次注册/登录个新用户;

    然后,会进入账号设置页面;

    我们放开断点;因为,accountInfo.html页面,会同时访问【获得用户账户信息,接口】和【获得用户基本信息,接口】;所以,其在后端,其实会调用两次getUser()方法的;所以,这儿的断点我们需要放开两次(在IDEA中,可以按F9),这样一来accountInfo.html页面需要的数据才能准备好,这个页面才能完全加载好;

    step2:去更新/完善用户信息;

    ……………………………………………………

    自然,我们更新用户信息后,accountInfo.html页面会重新加载;

    自然,因为要获取“用户账户信息”(通过访问【获得用户账户信息,接口】获得),,,也要获得“用户基本信息”(Session Storage中有,就从Session Storage中拿;;;Session Storage中没有,就通过访问【获得用户基本信息,接口】获得;;;因为,在更新用户信息的时候,前端代码把浏览器中的Session Storage存的用户基本给清掉了,,,所以这儿也是需要调用【获得用户基本信息,接口】的);;;;所以,其在后端,其实会调用两次getUser()方法的;

    这儿的断点我们需要放开两次(在IDEA中,可以按F9),这样一来accountInfo.html页面需要的数据才能准备好,这个页面才能完全加载好;

    PS:因为在accountInfo.html上,(如果Session Storage中没有“用户基本信息”的话) 会调用两次后端的getUser()方法;;;这不太方便我们观察效果;;;所以,我们将在首页上去测试;

    下面就是首页;

    一个前端的、未解决的问题;

    某个页面在session storage中创建的“用户基本信息”,其他页面使用不了吗?(这是前端的知识~~~~,自己不太能搞懂)

    (1)情况描述;

    然后,

    但是,当我们点击左上角的【慕课新闻】后,进入index.html页面;

    (2)疑问;
    问题1:不是说好的,index.html页面只会尝试去获取“用户基本信息”吗(而不会获取“用户账户信息”);;;;既然,是获取“用户基本信息”;;;;我们前面已经把用户基本信息存到Session Storage中了;;;;其为什么还要调用后端的接口;
    问题2:为什么【我们在accountInfo.html这个页面上,保存到Session Storage中的“用户基本信息”】,在index.html页面上查看,却不在了? 

    (3)交代:

              ● 讲道理,这个(主要是前端范围的内容)问题自己不是很懂,真要搞明白,估计需要花费很大的精力~~~算了,暂时搁置的~~

              ● 这儿没有错,主要是对于Session Storage自己在上篇博客中,一开始理解错了;;Session Storage不能跨窗口;具体可以参考上篇博客【32:第三章:开发通行证服务:15:浏览器存储介质,简介;(cookie,Session Storage,Local Storage)】;

    step3:Redis缓存效果演示;

    (1)Redis中有缓存数据时;

    ……………………………………………………

    F8单步调试,

    F9让其走完之后,页面OK了,可以Session Storage中也有了“用户基本信息”;


    (2)Redis中没有缓存数据时;

     


    (3)如果我们把Session Storage中的用户信息给清掉,再刷新页面的话,其就是从Redis中获取了;

  • 相关阅读:
    Redis的数据删除策略
    [要素察觉]C语言五讲:指针
    cpp中的函数模板
    图扑 3D 可视化国风设计 | 科技与文化碰撞炫酷”火花“
    设计模式java版本阅读笔记 一 创建型
    T113-S3-buildroot文件系统tar解压缩gz文件
    使用opencv实现图像的畸形矫正:仿射变换
    python数据可视化-matplotlib入门(2)-利用随机函数生成变化图形
    【开源】基于Vue和SpringBoot的中小学教师课程排课系统
    【多任务案例:猫狗脸部定位与分类】
  • 原文地址:https://blog.csdn.net/csucsgoat/article/details/125612996