当前位置:网站首页>33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)
33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)
2022-07-05 16:40:00 【小枯林】
说明:
(1)声明:这个其中的区别和相同点,要清楚;
● 在【32:第三章:开发通行证服务:15:浏览器存储介质,简介;】中,前端使用【把“用户基本信息”存到Session Storage中】来减轻后端接口的压力;;;;这是,从前端的角度出发,来减轻后端接口的压力;
● 本篇博客,使用Redis缓存用户信息,是利用Redis来减轻访问数据库的压力;
● 这两篇博客的内容,其目的差不多,都是降低系统压力,提高并发量;;;;但是,其着力点和具体做法存在差异的;
(2)以前在【Spring Boot电商项目31:商品分类模块十:利用Redis缓存加速响应;】、【附加:【Spring Boot缓存】【Redis】;】介绍过在利用Redis缓存的案例;虽然和本篇博客在技术上存在差异,但其目的是差不多的;有点条条大路通罗马的感觉;
目录
1.修改getUser()方法的逻辑:redis中有用户信息,就从redis中拿;redis中没有用户信息,就从数据库中查,同时把查到的用户信息存到redis中去;
2.当调用【修改/完善用户信息,接口】修改了用户信息后,我们也要及时的去更新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()方法的逻辑;
/** * 公用方法:根据userId去查user; * @param userId * @return */ private AppUser getUser(String userId) { // 说明:由于“用户信息”不太常会变动;对于一些千万级别的网站来说,当某个用户第一次查询用户信息的时候, // 这些信息我们完全可以使用redis缓存起来;这样一来,用户后续再获取信息的时候,就可以从redis中 // 获取,就不用查询数据库了; AppUser user = null; //(1)去redis中查一查,看redis中是否已经有了这个用户的用户信息; String userJson = redisOperator.get(REDIS_USER_INFO + ":" + userId); //(2.1)如果redis中,已经有了该用户的信息:那么我们就把JSON中用户信息,转成对应的AppUser对象; if (StringUtils.isNotBlank(userJson)) { user = JsonUtils.jsonToPojo(userJson, AppUser.class); } else { //(2.2)如果redis中,没有该用户的信息(那么,极大概率是,用户这是第一次来查询用户信息),那么我们 // 就查询数据库,去数据库中获取用户信息; user = userService.getUser(userId); //同时,把查到的用户信息,存到redis中去;(以便,让用户在后面第二次想要查询用户信息的时候,就 // 可以直接从redis中拿了,就不用再操作数据库了) redisOperator.set(REDIS_USER_INFO+":"+userId,JsonUtils.objectToJson(user)); } //(2.3)返回user用户对象 return user; }
说明:
(1)修改内容;
(2)逻辑分析;
● 看注释;
● 因为,我们这儿要操作redis,所以这个类需要注入RedisOperator这个工具类的对象;
● 我们在向redis中存用户信息的时候,其key是【redis_user_info:用户id】这种格式;
2.当调用【修改/完善用户信息,接口】修改了用户信息后,我们也要及时的去更新redis中的用户信息;
UserServiceImpl中的updataUserInfo()方法;
/** * 修改/完善用户信息,并且激活用户; * * @param updateUserInfoBO */ @Override public void updateUserInfo(UpdateUserInfoBO updateUserInfoBO) { //把前端传过来的updateUserInfoBO中的属性值,copy到一个AppUser对象中去; AppUser userInfo = new AppUser(); BeanUtils.copyProperties(updateUserInfoBO, userInfo); //重新设置其更新时间 userInfo.setUpdatedTime(new Date()); //设置其用户状态,把其状态设为1(即已激活); userInfo.setActiveStatus(UserStatus.ACTIVE.type); //和mybatis-plus的套路基本一样,我们使用updateByPrimaryKeySelective()方法(这个方法只去更新数据库表中那些userInfo中有的,,没有的不会动); // 而不使用updateByPrimaryKey();(这个方法会全部更新数据库表的内容,,userInfo没有的,就会设为空了), int result = appUserMapper.updateByPrimaryKeySelective(userInfo); if (result != 1) {//如果上面方法的返回值不为1,就表示这个更新操作出了问题,那么我们就抛出一个异常; GraceException.display(ResponseStatusEnum.USER_UPDATE_ERROR); } //能走到这一步,说明用户信息更新是OK的;那么,此时我们去获取最新的用户信息,把其存到redis中去; String userId = updateUserInfoBO.getId(); AppUser user = getUser(userId); redisOperator.set(REDIS_USER_INFO+":"+userId, JsonUtils.objectToJson(user));//这个会覆盖掉旧值 }
说明:
(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中获取了;
边栏推荐
- How does the outer disk futures platform distinguish formal security?
- American chips are no longer proud, and Chinese chips have successfully won the first place in emerging fields
- Combined use of vant popup+ other components and pit avoidance Guide
- Embedded UC (UNIX System Advanced Programming) -3
- WSL2.0安装
- ternary operator
- 【jmeter】jmeter脚本高级写法:接口自动化脚本内全部为变量,参数(参数可jenkins配置),函数等实现完整业务流测试
- Embedded-c Language-3
- [729. My schedule I]
- What else do you not know about new map()
猜你喜欢
Embedded UC (UNIX System Advanced Programming) -3
SQL injection of cisp-pte (Application of secondary injection)
[Jianzhi offer] 63 Maximum profit of stock
一个满分的项目文档是如何书写的|得物技术
[729. My Schedule i]
高数 | 旋转体体积计算方法汇总、二重积分计算旋转体体积
Use JDBC technology and MySQL database management system to realize the function of course management, including adding, modifying, querying and deleting course information.
ECU introduction
拷贝方式之DMA
npm安装
随机推荐
American chips are no longer proud, and Chinese chips have successfully won the first place in emerging fields
Embedded -arm (bare board development) -2
Combined use of vant popup+ other components and pit avoidance Guide
[brush questions] effective Sudoku
一个满分的项目文档是如何书写的|得物技术
Embedded-c Language-5
How does the outer disk futures platform distinguish formal security?
Application of threshold homomorphic encryption in privacy Computing: Interpretation
C how TCP restricts the access traffic of a single client
Games101 notes (I)
兰空图床苹果快捷指令
Machine learning compilation lesson 2: tensor program abstraction
SQL injection of cisp-pte (Application of secondary injection)
Use JDBC technology and MySQL database management system to realize the function of course management, including adding, modifying, querying and deleting course information.
Jarvis OJ 简单网管协议
【机器人坐标系第一讲】
CMake教程Step2(添加库)
干货!半监督预训练对话模型 SPACE
EasyX second lesson
China Radio and television officially launched 5g services, and China Mobile quickly launched free services to retain users