精华内容
下载资源
问答
  • 在业务环境中,频繁访问数据库获取数据的做法是不可取的,为了提升数据请求的效率,目前比较流行的做法就是使用 Redis 缓存服务,将频繁被请求的数据缓存起来,在下一次数据被请求时,根据设定的 key 返回相应的数据...

    前言

    在业务环境中,频繁访问数据库获取数据的做法是不可取的,为了提升数据请求的效率,目前比较流行的做法就是使用 Redis 缓存服务,将频繁被请求的数据缓存起来,在下一次数据被请求时,根据设定的 key 返回相应的数据。但是,缓存系统的存在,就导致数据库和 Redis 之间需要我们考虑其数据同步的问题。由于两者的数据更新必然不是同时进行的,因此当其中一方出现数据更新时,正在进行的访问就有可能从另一方获取到“肮脏”的数据。接下来,我们就分析一下可能存在的几种方案以及他们各自的优缺点。

    方案一:懒加载

    服务运行时,Redis 缓存中没有数据,直至接收到数据请求之后,才会去访问数据库获取数据进行返回,并将数据同步到缓存。

    这里的缓存更新是由用户请求进行触发的,每一次出现对新数据的请求时,就要对数据库进行一次访问。因此,在并发请求的场景下,缓存数据不存在时,所有的并发请求就会直接打了数据库上,给数据库带来极大的负载,容易造成数据库宕机,影响其他依赖的服务。这种方案一般会伴随着分布式锁,保证一次只能有一个请求访问数据库,并更新缓存,其他请求只能等待该请求完成响应后,直接访问缓存数据。

    方案二:手动触发更新,覆盖旧缓存,删除无效缓存

    这里的手动触发,是指后台工作人员通过操作启动,亦或是设置定时任务运行更新任务。更新任务触发后,系统会从数据库查询最新的数据集合,覆盖原有的缓存数据,其余的缓存视为无效数据,直接删除。

    这个方案保证了任意时刻缓存与数据库都能存在可用的数据,而且能够及时清除无效的缓存数据。但是,该方案的逻辑相对比较复杂,每次更新都需要筛选出不进行缓存覆盖的数据所对应的 key,才能删除无效缓存。这种更新机制与业务内容存在着强关联,无法通用。

    方案三:手动触发更新,删除原缓存数据

    后台工作人员主动启动缓存更新任务,从数据库批量获取最新的数据集合,然后删除当前缓存的数据,将新数据插入到缓存中。

    该方案在更新过程中,缓存在某一段时间内存在没有特定缓存数据的情况,如果此时刚好有业务在进行查询,有可能会获取到数据删除前的旧数据或者空数据,影响业务进行。在业务过程中删除缓存数据的操作容易影响业务功能和用户体验,因此一般不推荐使用该方案。

    方案四:缓存预加载

    预加载的思想在于,在请求到达之前,Redis 预先将数据加载到缓存;当请求到来后,直接通过 key 从 Redis 中获取已经提前缓存好的数据,而不需要去访问数据库。

    合理设计缓存关键字 key 可以有效解决上述三个方案存在的问题。通过在业务空闲时执行定时更新任务对缓存数据进行更新,这样就避免了更新缓存的操作影响了业务功能,同时自动化执行释放了工作人员的操作压力。再者,将 key 由数据关键字与当前时间戳进行组合,则可以用来标识数据及其写入缓存的时间,这个时间戳可以用作区分前后两次缓存的数据。当我们从数据库获取到新的数据时,新的 key 带了新的时间戳,将新数据写入缓存,此时新旧两份数据同时存在。在确保缓存更新完成后,再进行切换,使得外部请求能获取到最新的缓存,之后再对旧的缓存进行删除或者设置一个较短的过期时间,使之消失。

    这个方案在大部分业务场景中都非常适用,唯一存在的不足时,它对 Redis 内存的要求较高,因为预加载需要提前完成缓存,由于不确定哪些数据是不会被访问到的,因而几乎所有数据都需要进行缓存,容易造成 Redis 内存的滥用。

    展开全文
  • 每天定时从数据库中搜索数据,然后更新redis中。 通过java的Timer和quartz都分别能实现定时任务更新redis中的数据, 但导师对这样的实现并不满意, 导师的想法是能否通过相关的工具来保证定时更新的可靠性。 ...
  • 需求:点击菜单时统计菜单的点击数量,由于菜单点击很频繁,采用redis缓存定时存入mysql // 添菜单使用情况存入redis public PageData addRedis(PageData pd) { // 将对象转换成json字符串 String pdJson = JSON...

    需求:点击菜单时统计菜单的点击数量,由于菜单点击很频繁,采用redis缓存再定时存入mysql

    // 添菜单使用情况存入redis
    public PageData addRedis(PageData pd) {
            // 将对象转换成json字符串
            String pdJson = JSON.toJSONString(pd);
             // 存入的时候key值前面加入应该常量取出来好取
            redis.set(MENUS_CLINK_REDIS+"_"+StringUtil.getUUID(),pdJson);
            return RespUtil.getSuccessResp();
        }
    
    
    
    // 从redis取出存入mysql
     @Scheduled(cron=" 0 0/2 * * * ?")  // 二分钟执行一次
        public void addMySql() {
            Set<String> keys = redis.scan(MENUS_CLINK_REDIS+"_"+"*");
            if (keys != null) {
                for (String key : keys) {
                    String pdJson = redis.get(key);
                    PageData pageData = JSON.parseObject(pdJson, PageData.class);
                    countMenusMapper.add(pageData);
                    redis.delete(key);
                }
            }
        }
    @EnableScheduling //开启定时任务
    @SpringBootApplication
    public class Start {
    	public static void main(String[] args) throws Exception {
    		SpringApplication.run(Start.class, args);
    	}
    }
    

    上面的定时任务在只有一个定时任务才能顺利执行,要是有多个定时任务就需要一个线程池,进行异步调用。

    加上一个@EnableAsync

    @EnableScheduling //开启定时任务
    @EnableAsync //开启线程异步
    @SpringBootApplication
    public class Start {
    	public static void main(String[] args) throws Exception {
    		SpringApplication.run(Start.class, args);
    	}
    }
    

    配置应一个线程池类

    @Configuration
    public class ScheduleConfiguration implements SchedulingConfigurer {
    
        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            taskRegistrar.setScheduler(this.getTaskScheduler());
        }
        private ThreadPoolTaskScheduler getTaskScheduler() {
            ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
            taskScheduler.setPoolSize(20);
            taskScheduler.setThreadNamePrefix("schedule-pool-");
            taskScheduler.initialize();
            return taskScheduler;
        }
    }
    

    然后开启定时任务

     @Async   // 定时方法上加入进行异步
     @Scheduled(cron=" 0 0/2 * * * ?")  // 二分钟执行一次
        public void add1() {
           
        }
     @Async   // 定时方法上加入进行异步
     @Scheduled(cron=" 0 0/2 * * * ?")  // 二分钟执行一次
        public void add2() {
           
        }
    

    这样就可以多个定时任务异步执行

    展开全文
  • redis更新缓存

    2020-01-19 16:04:53
    今天对使用redis更新缓存整理几个方案,有不足的地方还望多多指正。 第一种: 方案:后台设置更新缓存按钮由操作人员操作或者使用定时任务,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存; 问题:...

    当我们做项目时,总会遇到一些数据经常被查询,但是不会经常修改,对于这样的数据大家都会想到使用缓存处理。今天对使用redis更新缓存整理几个方案,有不足的地方还望多多指正。

    第一种:

    • 方案 :后台设置更新缓存按钮由操作人员操作或者使用定时任务,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存;
    • 问题:更新过程中删除掉缓存后刚好有业务在查询,那么这个时候返回的数据会是空,会影响用户体验;
    • 总结:影响用户体验一般不推荐使用;

    第二种:

    • 方案:后台设置更新缓存按钮由操作人员操作或者使用定时任务,从DB查找最新数据集合,这里不删除缓存,通过遍历数据覆盖和删除掉无效的数据;
    • 问题:逻辑处理相对麻烦,数据量大处理起来也比较耗时,而且更新的机制也无法通用;
    • 总结:更新逻辑写起来比较麻烦,而且更新方案不能抽象通用;

    第三种:

    • 方案:前台获取数据时先去读缓存,发现没有缓存数据在去数据库同步数据到缓存;
    • 问题:当并发请求获取缓存数据不存在的时候,就会产生并发的查询数据的操作,造成缓存穿透;
    • 总结:可以使用双重检测锁(示例代码:https://github.com/itxiaobaishu/java-code.git),锁住更新操作只能有一个进入DB查询,可以避免问题;

    第四种:

    • 方案:前台获取缓存数据时先需要获取缓存的key,再根据缓存的key读取缓存数据;
    • 实现逻辑:举个简单的例子,完整的缓存由redis两条数据组成,第一条(key=cache,value=1111111111)、第二条(key=1111111111,value=缓存的具体数据),先通过第一条读出缓存的key,在根据key读取缓存数据。当有数据更新时,可以后台生成新的缓存数据(key=2222222222,value=新的缓存数据),同时更新(key=cache,value=2222222222),再把旧数据(key=1111111111,value=缓存的具体数据)设置一个过期时间,注意旧数据不要删除,可能有的业务还在使用;
    • 总结:使用预加载到缓存,然后在切换需要显示的缓存数据,可以很好的解决问题;
    展开全文
  • redis 缓存雪崩 缓存击穿 缓存穿透 概念 缓存雪崩 缓存击穿 缓存穿透 解释 同一时间大量key过期失效导致db因压力异常 某个热key失效大量请求导致db异常 数据库和缓存都没有存要访问数据,数据...
    redis 缓存雪崩 缓存击穿 缓存穿透
    概念缓存雪崩缓存击穿缓存穿透
    解释同一时间大量key过期失效导致db因压力异常某个热key失效大量请求导致db异常数据库和缓存都没有存要访问数据,数据量大db异常
    解决

    1.设置大量key随机过期时间

    2.根据业务场景定时预热数据

    3.分级缓存,不同级缓存过期时间不同。

    4.若是redis集群挂掉引发,则走降级,看db压力是否可以支撑。

    1.setnx命令确保只有一个请求处理

    2.设置热点数据不过期,异步更新

    1.强化参数校验避免产生异常数据访问

    2.将异常key缓存redis一段时间

    3.布隆过滤器

    展开全文
  • SpringBoot使用Redis实现 自动缓存 更新 删除 本篇主要讲述如何使用基本的注解 @Cacheable @CachePut @CacheEvict 操作缓存 1我们导入Redis的依赖 <!--这里Redis我给了版本--> <dependency> <...
  • 今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时...
  • ssm redis里面缓存更新

    2017-11-21 13:38:52
    (当我第一次查询数据库数据,缓存redis里面,再往数据库插入数据,此时再查询会查询到redis里面的缓存,怎么设置xml使数据库数据有更新redis会跟着重新缓存,或设置时间定时连接数据库缓存
  • Redis 更新缓存问题解决

    千次阅读 2019-03-21 16:47:39
    [主动]需要操作人员去操作,或者定时调度  [被动]由用户触发更新  [预加载]提前加载好数据 方案1 [主动]后台点击更新缓存按钮,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存; ...
  • Redis更新缓存策略

    万次阅读 2019-03-28 11:04:03
    [主动]需要操作人员去操作,或者定时调度  [被动]由用户触发更新  [预加载]提前加载好数据 方案1 [主动]后台点击更新缓存按钮,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存; 问题:更新...
  • Redis 缓存更新策略

    千次阅读 2020-03-30 18:19:19
    Redis缓存设计 一、缓存的收益与成本 1.1 收益 加速读写:因为缓存通常都是全内存的(例如Redis、Memcache),而存储层通常读写性能不够强悍(例如MySQL),内存读写的速度远远高于磁盘I/O。通过缓存的使用可以...
  • 第一篇记录一下在springboot中,redis的基础用法,自动缓存新增的数据,自动修改及删除。 在本机安装好mysql和redis。新建一个springboot的web项目,在新建项目时勾选redis,mysql。 pom文件如下: <?xml ...
  • redis缓存更新策略

    2020-03-04 18:47:34
    Redis缓存设计原则 只应将热数据放到缓存中 所有缓存信息都应设置过期时间 缓存过期时间应当分散以避免集中过期 缓存key应具备可读性 应避免不同业务出现同名缓存key 可对key进行适当的缩写以节省内存空间 ...
  • 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。 这样处理,主要是实时读写redis,而...
  • redis基础及缓存策略

    2020-12-14 22:27:03
    我们都知道redis是基于内存,单线程机制工作,查询速度快,效率高,一般在项目种常用来做缓存,但是具体的缓存策略是什么呢? 读且成功:用户从redis中读取数据,如果读取到了,直接使用 读且失败:如果用户没有从...
  • redis搜索联想缓存方案设计 欢迎关注作者博客 简书传送门 页面原型 缓存词库 说明: 建议所有的请求都走异步调用 常用搜索词库数据统计规则: 每天晚上12点定时取出所有人词库中排名靠前10位的搜索项并放入常用...
  • Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间 件。 它支持多种类型的数据结构,如字符串(String),散列(Hash),列表(List),集合 (Set),有序集合(Sorted Set...
  • SpringBoot + Redis 实现缓存 一、在pom中添加依赖 <!--springboot redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-...
  • 缓存预热 缓存预热,是指系统上线后,先将数据加载...缓存更新,是指根据需要定期或触发清理过期或不需要的缓存。 缓存降级 缓存降级,是为保证核心服务可用,使部分关键数据自动降级,同时也可避免缓存雪崩。 ...
  • redis缓存更新分为:内存溢出淘汰策略、过期删除策略、应用方更新 一、内存溢出淘汰策略 当redis所用内存达到maxmemory时(use_memory>maxmemory),会触发相应的溢出控制策略,具体策略可配 根据LRU算法删除...
  • 如何通过 Redis 构建分布式缓存技术

    千次阅读 2018-01-25 00:00:00
    本文来自作者 默默 在 GitChat 上分享 「如何通过 Redis 构建分布式缓存技术」,「阅读原文」查看交流实录。「文末高能」编辑 | 哈比Redis 基础Redis 是基于内存的,存储形式为 key-value 的非关系型数据库,它...
  • 缓存淘汰策略、Redis事务、Redis持久化 目标 理解缓存淘汰的LRU策略 理解Redis事务的应用、乐观锁的实现 Redis缓存淘汰策略 设置最大缓存redis 中,允许用户设置最大使用内存大小maxmemory(redis.config里...
  • 我们来介绍Redis使用过程中需要注意的三种问题:缓存穿透、缓存击穿、缓存雪崩。 1.缓存穿透 1.1.概念 缓存穿透:缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮...
  • Redis中常见缓存问题解析

    千次阅读 2020-04-07 23:35:16
    在此解析一下Redis缓存中常见的四个问题:缓存预热、缓存雪崩、缓存穿透、缓存降级。 缓存预热 当用户查询一个数据时,会先到数据库进行查询,再将查询到的数据进行缓存。为了避免这个问题,在用户查询前就将缓存...
  • 分布式缓存问题:Redis 的缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念一、缓存雪崩缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在...
  • 1:引入springboot redis的maven依赖(建议使用spring-boot-dependencies或者使用spring-io-platform进行构建项目) &lt;dependency&gt; &lt;groupId&gt;org.springframework.data&lt;/groupId...
  • 使用redis做mysql缓存

    2019-10-08 04:46:25
    同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。 这样处理,主要是实时读写redis,而...
  • 大话Redis进阶-更新缓存的问题 使用Redis过程中,总是会遇到各种各样问题,这里进行问题的总结,作为Redis 进阶的经验分享。 更新缓存的问题 [主动]需要操作人员去操作,或者定时调度 [被动]由用户触发更新 [预...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,673
精华内容 15,869
关键字:

redis定时更新缓存

redis 订阅