利用Redis解决缓存击穿问题

缓存击穿

也叫做热点key问题,就是一个高并发访问并且重建业务较为复杂的key突然失效,无数的请求访问会在瞬间给数据库带来巨大的压力

解决策略

解决方案 优点 缺点
互斥锁 没有额外的内存消耗 保证数据一致性 实现简单 线程需要等待,性能受到影响 可能有死锁的风险
逻辑过期 线程无需等待,性能较好 不保证一致性 有额外的内存消耗 实现复杂

下面以访问用户分页信息为例,分别加上采取互斥锁和逻辑过期策略

互斥锁

代码逻辑

同一时刻只允许一个线程查询数据库,请求成功后将数据存入redis

其余线程则一直等待,直到缓存中存在数据

PS: 可以利用redis的setnx方法(只能在第一次成功设置值,以后设置将会失败),模拟锁的获取

ini 复制代码
//  互斥锁解决缓存击穿
public Result queryWithMutex(int page, int pageSize, String name){
    String mykey = EMPLOYEE_PAGE_PREFIX + "page" + page + "_" + "pageSize" + pageSize + "_" + "name"+ name;
    Page<Employee> pageList = null;
    //从缓存中查询是否存在
    Object o = redisUtils.get(mykey);
    //缓存中没有page信息
    if(o==null){
        String lockKey = EMPLOYEE_LOCK_PREFIX+ "page"+ page + "_" + "pageSize" + pageSize + "_" + "name"+ name;
        try {
            // 1.获取互斥锁
            boolean b = tryLock(lockKey);
            int count = 1;
            // 2. 判断是否读取成功
            while(!b){
                // 3. 失败,则休眠重试
                Thread.sleep(100);
                log.info("已经有线程占有锁,休眠后再次查询,这是第{}次休眠",count++);
                b = tryLock(lockKey);
                if(b){
                    o = redisUtils.get(mykey);
                    log.info("休眠后发现缓存有值了,请求到redis");
                    pageList = JSON.parseObject(o.toString(), Page.class);
                    unlock(lockKey);
                    return Result.success(pageList);
                }
            }

            log.info("我是第{}个进入线程,直接查询数据库",number++);
            pageList = queryPageAndSave(page,pageSize,name,mykey);
        }catch(InterruptedException e){
            throw new RuntimeException();
        }finally{
            // 释放互斥锁
            unlock(lockKey);
        }
    }
    else{
        log.info("直接请求redis的");
        pageList = JSON.parseObject(o.toString(), Page.class);
    }
    return Result.success(pageList);
}

情景模拟

此时redis没有缓存,将会有100个线程在1S内同时访问,下图为部分控制台输出

只有一个线程能够访问数据库,其余线程均会休眠。可以根据任务完成的速度,设置线程的休眠时间。

逻辑过期

代码逻辑

保存时候额外添加带有逻辑过期时间的字段,使用了逻辑过期替代TTL。这样redis中永远都有值,虽然这会导致用户访问到旧的数据。

ini 复制代码
// 保存带有逻辑过期时间的字段
public Page saveEmployeeWithLogicExpire(int page, int pageSize, String name,Long expireSeconds) {
    log.info("开始查询数据库信息");
    // 查询店铺信息
    Page queryPage = queryPage(page, pageSize, name);
    // 封装逻辑过期时间
    RedisData data = new RedisData();
    data.setData(queryPage);
    data.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));
    //写入到redis缓存
    String key = EMPLOYEE_PAGE_PREFIX + "page" + page + "_" + "pageSize" + pageSize + "_" + "name"+ name;
    String value =JSON.toJSONString(data);
    redisUtils.set(key,value);

    return queryPage;
}

下面代码的逻辑是:当缓存中不存在所求信息,或者逻辑过期时间已到,需要去数据库查询数据更新到redis中。此时,第一个进入方法的线程负责查询更新操作,其余线程会从已有的redis缓存中取出。若缓存中没有,即高并发且第一次访问时候,还会产生缓存击穿问题。

ini 复制代码
//线程池
private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);
// 逻辑过期解决缓存击穿
public Result queryWithLoginExpire(int page, int pageSize, String name){
    String mykey = EMPLOYEE_PAGE_PREFIX + "page" + page + "_" + "pageSize" + pageSize + "_" + "name"+ name;
    Page<Employee> pageList = null;
    //从缓存中查询是否存在
    Object o = redisUtils.get(mykey);
    // 缓存中存在
    if(o!=null ){
        //命中,先把json反序列化为对象
        RedisData redisData = JSON.parseObject(o.toString(), RedisData.class);
        // 获取分页和逻辑过期时间
        Page page1 = JSON.parseObject(redisData.getData().toString(), Page.class);
        LocalDateTime expireTime = redisData.getExpireTime();

        // 判断是否过期
        if(expireTime.isAfter(LocalDateTime.now())){
            log.info("逻辑时间还没到,直接从redis中返回员工信息");
            //未过期,直接返回员工信息
            return Result.success(page1);
        }

        // 已过期,需要缓存重建
        String key = EMPLOYEE_LOCK_PREFIX + "page" + page + "_" + "pageSize" + pageSize + "_" + "name"+ name;
        boolean b = tryLock(key);

        // 更新缓存信息
        if(b) {
            CACHE_REBUILD_EXECUTOR.submit(()->{
                log.info("逻辑时间已过,更新员工信息");
                // 重建缓存
                Page  page2 =  this.saveEmployeeWithLogicExpire(page, pageSize, name,EMPLOYEE_LOCK_EXPIRE);
                // 释放锁
                unlock(key);
                return  Result.success(page2);
            });
        }
        // 其余线程返回旧的信息
        log.info("已经有线程在更新,返回旧的数据");
        return Result.success(page1);
    }
    else {
        //缓存中不存在,查询数据库并且存入缓存
        log.info("redis中不存在,查询数据库信息");
        Page page1 = saveEmployeeWithLogicExpire(page, pageSize, name, EMPLOYEE_LOCK_EXPIRE);
        return Result.success(page1);
    }
}

情景模拟

初始状态

此时redis缓存为空,有100个线程在1秒内访问分页内容

以下展示部分控制台信息,初始化高并发访问仍会出现缓存击穿

yaml 复制代码
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f3757c3] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b925a02] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53bc6b0b] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1602ed6a] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@24f7d7f2] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3364860a] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@457a807f] was not registered for synchronization because synchronization is not active
2023-06-08 00:28:12.161  INFO 52980 --- [io-8081-exec-43] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-06-08 00:28:12.655  INFO 52980 --- [io-8081-exec-43] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@2106806061 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e216c0] will not be managed by Spring
JDBC Connection [HikariProxyConnection@1338578974 wrapping com.mysql.cj.jdbc.ConnectionImpl@727d514d] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==>  Preparing: SELECT COUNT(*) AS total FROM employee
JDBC Connection [HikariProxyConnection@461634391 wrapping com.mysql.cj.jdbc.ConnectionImpl@145b03f7] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
==> Parameters: 
==> Parameters: 
JDBC Connection [HikariProxyConnection@1007102482 wrapping com.mysql.cj.jdbc.ConnectionImpl@109dd549] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
JDBC Connection [HikariProxyConnection@411223316 wrapping com.mysql.cj.jdbc.ConnectionImpl@527d23ab] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
JDBC Connection [HikariProxyConnection@639844861 wrapping com.mysql.cj.jdbc.ConnectionImpl@9928553] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
JDBC Connection [HikariProxyConnection@240348441 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
JDBC Connection [HikariProxyConnection@377573666 wrapping com.mysql.cj.jdbc.ConnectionImpl@68286884] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
<==    Columns: total
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5f58ffac]
JDBC Connection [HikariProxyConnection@979270653 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ea15164]
JDBC Connection [HikariProxyConnection@1742701579 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@68563e11]
JDBC Connection [HikariProxyConnection@1933071623 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b925a02]
JDBC Connection [HikariProxyConnection@782494353 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@24f7d7f2]
JDBC Connection [HikariProxyConnection@583545093 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2f824173]
JDBC Connection [HikariProxyConnection@2051368544 wrapping com.mysql.cj.jdbc.ConnectionImpl@727d514d] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==    Columns: total
<==        Row: 6
<==      Total: 1
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@180b57fa]
JDBC Connection [HikariProxyConnection@1143773205 wrapping com.mysql.cj.jdbc.ConnectionImpl@3e0ff29f] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==    Columns: total
<==        Row: 6
<==      Total: 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==      Total: 2
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@622a7c88]
JDBC Connection [HikariProxyConnection@1758121299 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e216c0] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM employee
==> Parameters: 
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==    Columns: total
<==        Row: 6
<==      Total: 2
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@45b64fe]

逻辑时间未过

此时逻辑时间未过,无需查询数据库,从redis缓存中获取即可

yaml 复制代码
2023-06-08 00:34:18.566  INFO 55516 --- [io-8081-exec-11] o.s.web.servlet.DispatcherServlet        : Completed initialization in 16 ms
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-37] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-87] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-12] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-71] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-89] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-80] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [nio-8081-exec-9] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-66] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.828  INFO 55516 --- [io-8081-exec-60] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-53] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-14] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-44] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-27] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-41] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [nio-8081-exec-6] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-78] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-10] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-34] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-22] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息
2023-06-08 00:34:22.859  INFO 55516 --- [io-8081-exec-50] c.e.d.service.impl.EmployeeServiceImpl   : 逻辑时间还没到,直接从redis中返回员工信息

逻辑时间已过

此时逻辑时间已过,需要去数据库重新查询信息,此次更新只查询了一次数据库

yaml 复制代码
2023-06-08 00:39:14.097  INFO 55516 --- [o-8081-exec-113] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.096  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.097  INFO 55516 --- [o-8081-exec-101] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.097  INFO 55516 --- [o-8081-exec-102] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.096  INFO 55516 --- [o-8081-exec-111] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:true
2023-06-08 00:39:14.096  INFO 55516 --- [io-8081-exec-22] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.097  INFO 55516 --- [io-8081-exec-64] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.097  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.097  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.101  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.106  INFO 55516 --- [o-8081-exec-101] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.106  INFO 55516 --- [o-8081-exec-110] 
2023-06-08 00:39:14.325  INFO 55516 --- [o-8081-exec-116] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.326  INFO 55516 --- [o-8081-exec-116] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.326  INFO 55516 --- [o-8081-exec-103] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.326  INFO 55516 --- [o-8081-exec-103] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.335  INFO 55516 --- [o-8081-exec-119] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.335  INFO 55516 --- [o-8081-exec-119] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.337  INFO 55516 --- [o-8081-exec-115] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.337  INFO 55516 --- [o-8081-exec-115] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.345  INFO 55516 --- [o-8081-exec-117] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.345  INFO 55516 --- [o-8081-exec-117] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.347  INFO 55516 --- [o-8081-exec-107] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.347  INFO 55516 --- [o-8081-exec-107] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.356  INFO 55516 --- [o-8081-exec-109] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.356  INFO 55516 --- [o-8081-exec-109] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.357  INFO 55516 --- [o-8081-exec-105] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.357  INFO 55516 --- [o-8081-exec-105] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.368  INFO 55516 --- [o-8081-exec-121] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.368  INFO 55516 --- [o-8081-exec-121] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.369  INFO 55516 --- [io-8081-exec-22] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.369  INFO 55516 --- [io-8081-exec-22] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.375  INFO 55516 --- [o-8081-exec-102] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.375  INFO 55516 --- [o-8081-exec-102] 
2023-06-08 00:39:14.454  INFO 55516 --- [o-8081-exec-101] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.454  INFO 55516 --- [o-8081-exec-101] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.468  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.468  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.477  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.478  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.487  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.487  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.497  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.497  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.500  INFO 55516 --- [pool-2-thread-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-06-08 00:39:14.507  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.507  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.519  INFO 55516 --- [nio-8081-exec-1] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.519  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.519  INFO 55516 --- [nio-8081-exec-1] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.519  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.527  INFO 55516 --- [io-8081-exec-46] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.528  INFO 55516 --- [io-8081-exec-46] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:14.537  INFO 55516 --- [o-8081-exec-113] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:14.537  INFO 55516 --- [o-8081-exec-113] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.273  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
==> Parameters: 
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
==>  Preparing: SELECT COUNT(*) AS total FROM employee
2023-06-08 00:39:15.273  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.273  INFO 55516 --- [o-8081-exec-110] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
==> Parameters: 
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-108] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [o-8081-exec-120] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-75] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 此次请求的结果为:false
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-99] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
2023-06-08 00:39:15.461  INFO 55516 --- [io-8081-exec-35] c.e.d.service.impl.EmployeeServiceImpl   : 已经有线程在更新,返回旧的数据
<==    Columns: total
<==        Row: 6
<==      Total: 1
==>  Preparing: SELECT id,name,username,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1663073285396586498, 8888555, 1234, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 333333333333333333, 1, 2023-05-29 14:42:24, 2023-06-07 23:14:03, 1, 1
<==        Row: 1664913382693785601, zhsss, zhangsan, e10adc3949ba59abbe56e057f20f883e, 13365698890, 0, 340820200010020131, 1, 2023-06-03 16:34:18, 2023-06-03 16:34:18, 1, 1
<==      Total: 2
相关推荐
2401_857622666 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589366 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没8 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch8 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码9 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries10 小时前
读《show your work》的一点感悟
后端
A尘埃10 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-230710 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code10 小时前
(Django)初步使用
后端·python·django
代码之光_198010 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端