一:背景介绍
redis中存储了关于一个课程下多个班级的信息。但是难免会在一个课程下添加新的班级。添加了新的班级之后缓存中的数据是没有同步更新的,只能等数据的有效时间过了之后数据才会更新。这样就导致了我们添加了班级请求数据的时候却没有把新添加的数据返回回来。
此代码的逻辑是通过redis查询该课程下所有班级的信息,如果没有从redis中查询到数据就从数据库中查询并存到redis里一份。这样就存在一个问题,更新数据库中的数据的时候没有同步把缓存中的数据也进行更新,在查询的时候就会有查询的数据和实际的数据是不一致的。
二:思路&方案
在更新数据的时候,将redis中的缓存信息进行删除操作。下次在查询该数据的时候发现redis中没有该数据,就会从数据库中查询数据然后放到redis中,确保每次查询数据都是最新的。
三:过程
1.修改数据没有删除缓存
添加pom.文件的依赖
<dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>compile</scope> </dependency> </dependencies>
通过班级id查询课程名称
public class SelectCourseNameByClassId { /* * @description:通过班级id查询课程名称 * @author: wuzilong * @date: 2023/3/4 14:24 * @param: [args] * @return: void **/ public static void main(String[] args) { //构造jedis,连接redis 并设置超时时间为100秒,在jedis的默认构造方法中,超时的时间一般被默认设置为2000毫秒,也就是2秒。 Jedis jedis=new Jedis("ip",端口号,100000); jedis.auth("密码"); CourseConfiguration courseConfiguration=null; //查询redis String courseName = jedis.get("wuzilong:ClassId"); if(courseName==""||courseName==null){ //从数据库中查询 UserInfoDao userInfoDao=new UserInfoDao(); courseConfiguration = userInfoDao.selectCourseNameByClassId(55801751); //存入redis 并设置过期时间60秒 jedis.set("wuzilong:ClassId",courseConfiguration.getCourse_name()); jedis.expire("wuzilong:ClassId",60); System.out.println(courseConfiguration.getCourse_name()); }else { System.out.println(courseName); } } }
执行结果
通过班级id修改课程名称(没有删除redis中的缓存)
public class UpdateCourseNameByClassId { /* * @description:通过通过班级id修改班级名称 * @author: wuzilong * @date: 2023/3/4 14:27 * @param: [args] * @return: void **/ public static void main(String[] args) { //修改班级名称 UserInfoDao userInfoDao=new UserInfoDao(); userInfoDao.updateCourseNameByClassId(55801751,"ARPro计算机思维课程-开发班课"); System.out.println("修改成功!"); } }
执行结果
修改完毕之后我们在去执行一下通过班级id查询
发现查询出来的结果还是修改之前的结果, 这是由于redis缓存中之前的数据还没有过期。如果查询的时候对应的key的值已经过期了,那么会去数据库中查询数据然后放到redis。
2.修改数据删除了缓存
在原来修改数据的方法里添加了删除缓存的代码
public class UpdateCourseNameByClassId { /* * @description:通过通过班级id修改班级名称 * @author: wuzilong * @date: 2023/3/4 14:27 * @param: [args] * @return: void **/ public static void main(String[] args) { //修改班级名称 UserInfoDao userInfoDao=new UserInfoDao(); userInfoDao.updateCourseNameByClassId(55801751,"ARPro计算机思维课程-开发班课"); //连接redis Jedis jedis=new Jedis("82.157.199.3",6379,100000); jedis.auth("000415"); //删除key键 jedis.del("wuzilong:ClassId"); System.out.println("修改成功!"); } }
通过修改数据加上删除数据的缓存,我们就可以达到缓存中的数据和数据库中的数据是一致的。在给前端提供数据的时候不会有差异。
四:同步更新缓存
- 提高性能:Redis是一种基于内存的数据库,读取内存中的数据速度非常快。当数据发生修改时,Redis不会立即进行更新操作,而是将修改操作记录在内存中的日志中,然后异步地进行批量更新。这种延迟更新的方式可以减少磁盘IO操作,提高系统的整体性能。
- 减少网络开销:在分布式环境下,当多个客户端同时修改相同的数据时,如果每次修改都立即更新到Redis中,会导致大量的网络开销。延迟更新可以将多个修改操作合并成一次批量更新,减少了网络传输的次数和数据量,提高了系统的网络性能。
- 降低数据冲突风险:在高并发的场景下,多个客户端同时修改相同的数据可能会导致数据冲突,造成数据的不一致性。延迟更新可以通过将修改操作记录在内存中的日志中,然后按照一定的策略进行批量更新,减少了数据冲突的风险,提高了数据的一致性。
- 提高系统的可用性:Redis的延迟更新机制可以提高系统的可用性。当Redis节点发生故障或者网络中断时,延迟更新可以保证数据的一致性和完整性。在节点恢复或者网络重新连接后,Redis可以通过日志中的修改操作进行数据的恢复和更新,保证系统的可用性和数据的准确性。
五:总结
有时候很多的问题是我们没有想到或者对于知识的应用不清楚导致的。对于知识的学习还是需要系统性的学习,这样我们才会从很大程度上避免添加了缓存在数据更新的时候没有删除缓存的问题。
六:升华
1.学习要先宏观在微观,有了全面的认识之后在针对每一个模块进行学习。
2.做事情要有闭环反馈,有头有尾才能确保这件事情是一个完整的。