网站规划建设实训报告,界面交互设计,微信手机客户端网站建设,房产信息门户网站建设方案redis没有及时更新问题一#xff1a;背景介绍二#xff1a;前期准备pom依赖连接Redis工具类连接mysql工具类三#xff1a;过程使用redis缓存#xff0c;缓存用户年龄业务对应流程图使用redis缓存用户年龄对应代码四#xff1a;总结一#xff1a;背景介绍 业务中使用redis…
redis没有及时更新问题一背景介绍二前期准备pom依赖连接Redis工具类连接mysql工具类三过程使用redis缓存缓存用户年龄业务对应流程图使用redis缓存用户年龄对应代码四总结一背景介绍 业务中使用redis做缓存来减少对数据库的操作提升速度。使用的过程是 去redis内查询数据。如果有的话直接返回redis内的数据如果没有的话去数据库查询数据并将其存储到redis中那么下次的查询就是在redis内查询的省去了我们多次查询数据库的操作。 但是我们这个业务里redis内存的数据可能与数据库的不一致。导致这种现象的原因是。在另外的业务中更改了数据库内的数据后没有去修改redis内的数据于是造成了redis数据与数据库数据不一致的问题。下面我就用一个小例子演示上述问题以及解决方案
二前期准备
此实例是一个普通的maven项目。使用前需要准备好mysql数据redis。具体方式大家可以上网查询。
pom依赖
项目连接mysql和redis需要在maven内引入以下两个依赖. dependenciesdependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion3.3.0/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.46/version/dependency/dependencies连接Redis工具类
编写一个连接Redis的工具类这里直接使用的Jedis进行的连接。
/*** BelongsProject: redis* BelongsPackage: org.example.utils* Author:hlzs1* Description: redis的工具类* CreateTime: 2023-03-03 20:42* Version: 1.0*/
public class RedisUtils {public static Jedis jedis ;static {jedis new Jedis(ip地址,6379,10000);//没有设置密码可以不填jedis.auth(000415);}/*** description: 在redis取出数据* author: haolizhuo* date: 2023/3/4* param: [key]* return: java.lang.Object**/public static Object redisGet(String key){return RedisUtils.jedis.get(key);}/*** description:向redis存储数据* author: haolizhuo* date: 2023/3/4* param: [key, value, seconds]* return: void**/public static void redisSet(String key, String value, Nullable Integer seconds){RedisUtils.jedis.set(key,value);if(seconds !null){RedisUtils.jedis.expire(key,seconds);}}
}连接mysql工具类
连接mysql需要对应的配置文件新建一个jdbc.properties文件将此文件放到resources目录下即可
userNameroot
passworddeng123~
urljdbc:mysql://ip地址/数据库名?useSSLfalseuseUnicodetruecharacterEncodingutf8
driverClasscom.mysql.cj.jdbc.Driver连接数据库的工具类
/*** author : [haolizhuo]* version : [v1.0]* className : JDBCUtils* description : [描述说明该类的功能]* createTime : [2022/11/30 11:24]* updateUser : [haolizhuo]* updateTime : [2022/11/30 11:24]* updateRemark : [描述说明本次修改内容]*/
public class JDBCUtils {private static String url;private static String userName;private static String password;private static String driverClass;private static Connection connection;static {try {Properties properties new Properties();InputStream inputStream JDBCUtils.class.getClassLoader().getResourceAsStream(jdbc.properties);properties.load(inputStream);driverClass properties.getProperty(driverClass);url properties.getProperty(url);userName properties.getProperty(userName);password properties.getProperty(password);} catch (Exception e) {e.printStackTrace();}}/** version V1.0* Title: getConnection* author haolizhuo* description 获取数据库连接* createTime 2022/11/30 11:36* param []* return java.sql.Connection*/public static Connection getConnection() {try {connection DriverManager.getConnection(url, userName, password);} catch (Exception e) {e.printStackTrace();}return connection;}/** version V1.0* Title: close* author haolizhuo* description 释放资源* createTime 2022/11/30 11:39* param [connection, statement, resultSet]* return void*/public static void close(Connection connection, Statement statement, ResultSet resultSet) {if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}if (statement ! null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (resultSet ! null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}}项目结构
到这里我们真个环境就准备好了下面我们就复现背景里提到的使用缓存的情况
三过程
使用redis缓存缓存用户年龄
这里是一个普通的使用redis的场景我使用redis缓存了用户的年龄。key值是用户的idvalue值是用户的年龄。
业务对应流程图 使用redis缓存用户年龄对应代码 public static void main(String[] args) {//使用redis缓存,缓存某个id的用户的年龄这里以1做示例String userId 1;Object redisUserInfo RedisUtils.redisGet(userId);//如果缓存查到信息直接返回并且结束if(null ! redisUserInfo){System.out.println(redis获取到了用户userId的年龄年龄为 redisUserInfo);return;}//缓存里没有就去数据库进行查询String sql select * from user_info where id userId;MapString, Object userInfo getUserInfo(sql);//如果查询到了信息更新到缓存内if(userInfo ! null){System.out.println(mysql获取到了用户userId的年龄年龄为 userInfo.get(age));RedisUtils.redisSet(userInfo.get(id).toString(),userInfo.get(age).toString(),60);}}/*** description: 数据库查询用户数据* author: haolizhuo* date: 2023/3/4* param: [sql]* return: java.util.Mapjava.lang.String,java.lang.Object**/private static MapString, Object getUserInfo(String sql){Connection connection;Statement statement;ResultSet resultSet;MapString , Object map new HashMap(16);try {//创建数据库连接connection JDBCUtils.getConnection();statement connection.createStatement();resultSet statement.executeQuery(sql);//将值取出while (resultSet.next()){map.put(id,resultSet.getInt(id));map.put(name,resultSet.getString(name));map.put(age,resultSet.getInt(age));}} catch (SQLException e) {throw new RuntimeException(e);}return map;}这部分代码是没有问题通过redis做了对应缓存。如果缓存过期了之后就去数据库内查询并且更新到缓存中。但是问题是假设我们有别的业务更新了我们缓存的age数据同时redis的数据没有过期这是后就会造成一个数据不一致的问题。 执行代码控制台打印 查看redis内数据 查看数据库内数据 现在我们的数据是正确无误缓存与数据库数据一致。可如果我们的业务更新这个age的话就会产生不一致的问题 public static void main(String[] args) {String sql update user_info set age 66 where id 1;updateUserInfo(sql);}/*** description: 数据库修改用户数据* author: haolizhuo* date: 2023/3/4* param: [sql]* return: void**/private static void updateUserInfo(String sql){Connection connection;Statement statement;int resultSet;try {//创建数据库连接connection JDBCUtils.getConnection();statement connection.createStatement();resultSet statement.executeUpdate(sql);System.out.println(resultSet);} catch (SQLException e) {throw new RuntimeException(e);}}更新完之后redis内数据 更新完之后数据库内数据 这时候问题就暴露出来了缓存数据与数据库数据不一致。并且缓存的数据还未过期。导致过期前查询的数据都不准确。 所以在使用缓存的时候如果数据库内数据改了一定要及时的 清空缓存清空缓存清空缓存
四总结
这个问题的出现的根本原因是。不同的开发人员没有做好沟通这两个业务是不同的人员编写的没有考虑的业务的相关性导致了这种问题的出现 所以不仅仅要实现功能也要考虑业务相关性