利用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
相关推荐
Victor35619 分钟前
Redis(104)Redis的最大数据量是多少?
后端
Victor35625 分钟前
Redis(105)Redis的数据类型支持哪些操作?
后端
鬼火儿7 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin8 小时前
缓存三大问题及解决方案
redis·后端·缓存
间彧9 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧9 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
间彧9 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧9 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧9 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端
间彧9 小时前
Docker Compose和Kubernetes在编排服务时有哪些核心区别?
后端