精华内容
下载资源
问答
  • redis 缓存刷新

    千次阅读 2017-07-05 21:49:00
  • Redis系列 - Redis更新数据库还是先更新缓存? 先更新数据库再失效缓存

    Redis系列 - Redis缓存更新:先更新数据库还是先更新缓存?

    在更新缓存时,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实都会存在一定的问题。

    Cache Aside Pattern(旁路缓存模式)

    这是最常用的缓存使用方式了。其具体逻辑如下

    • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
    • 命中:应用程序从cache中取数据,取到后返回。
    • 更新:先把数据存到数据库中,成功后,再让缓存失效。

    我们更新时是先更新数据库,数据库更新成功后再让缓存失效。那么这种方式真的没有问题么?

    我们可以考虑一下以下的并发场景:

    1. 缓存key1刚好失效
    2. 请求A发起读请求没有命中缓存去数据库查询,此时查询出来的结果是老的数据
    3. 请求B发起更新请求,先更新数据库,
    4. 请求B让缓存失效
    5. 此时请求A将步骤2中读取出来的老数据写入缓存

    以上的并发场景理论上确实会发生导致脏数据的产生,但是在实际的生产环境中出现的概率非常低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。

    先删除缓存,再更新数据库

    改方案会导致数据不一致的原因如下:

    1. 请求A进行写操作,删除缓存(并更新数据库,此时还没更新)
    2. 请求B查询发现缓存不存在
    3. 请求B去数据库查询得到旧的值
    4. 请求B将旧的值写入缓存
    5. 此时请求A将新值更新进数据库

    这种情况下如果缓存不被更新或者被过期策略淘汰,那么这个数据将永远是脏数据。

    先更新数据库,再更新缓存

    我们可以看下以下的并发场景:

    1. 线程A和线程B同时去更新数据key1
    2. 线程A更新了数据库数据key1,此时value1
    3. 线程A更新了数据库数据key1,此时value2(最新的数据)
    4. 线程B更新的缓存key1的值为value2
    5. 线程A更新的缓存key1的值为value1

    由于线程A的更新数据库操作早于线程B,线程B更新的结果value2才是最新的结果,最终应该把value2放入缓存才符合实际的需求。但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此这种方案存在线程安全问题。

    先更新缓存,再更新数据库

    该方案不做考虑,若先更新缓存,缓存更新成功,但是更新数据库时发生异常导致回滚,那么缓存中的数据无法回滚,导致数据不一致。

     

     

    展开全文
  • Redis 缓存更新策略

    2020-03-30 18:19:19
    Redis缓存设计 一、缓存的收益与成本 1.1 收益 加速读写:因为缓存通常都是全内存的(例如Redis、Memcache),而存储层通常读写性能不够强悍(例如MySQL),内存读写的速度远远高于磁盘I/O。通过缓存的使用可以...

    Redis缓存设计

    一、缓存的收益与成本

    1.1 收益

    • 加速读写:因为缓存通常都是全内存的(例如Redis、Memcache),而存储层通常读写性能不够强悍(例如MySQL),内存读写的速度远远高于磁盘I/O。通过缓存的使用可以有效地加速读写,优化用户体验。

    • 降低后端负载:帮助后端减少访问量(Mysql设置有最大连接数,如果大量的访问同时达到数据库,而磁盘I/O的速度又很慢,很容易造成最大连接数被使用完,但Redis 理论最大)和复杂计算(例如很复杂的SQL语句),在很大程度降低了后端的负载。

    1.2 成本

    • 数据不一致性:缓存层和存储层的数据存在着一定时间窗口的不一致性,时间窗口跟更新策略有关。

    • 代码维护成本:加入缓存后,需要同时处理缓存层和存储层的逻辑,增大了开发者维护代码的成本。

    • 运维成本:以Redis Cluster为例,加入后无形中增加了运维成本。

    1.3 使用场景

    • 开销大的复杂计算:以MySQL为例子,一些复杂的操作或者计算(例如大量联表操作、一些分组计算),如果不加缓存,不但无法满足高并发量,同时也会给MySQL带来巨大的负担。

    • 加速请求响应:即使查询单条后端数据足够快,那么依然可以使用缓存,以Redis为例子,每秒可以完成数万次读写,并且提供的批量操作可以优化整个IO链的响应时间

    二、缓存更新策略

    2.1 内存溢出淘汰策略

    思考:在生产环境的 redis 经常会丢掉一些数据,写进去了,过一会儿可能就没了。是什么原因?

            Redis 缓存通常都是全内存,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。Redis 主要是基于内存来进行高性能、高并发的读写操作。那既然内存是有限,比如 redis 就只能用 10G,你要是往里面写了 20G 的数据,会咋办?当然会干掉 10G 的数据,然后就保留 10G 的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。数据明明过期了,怎么还占用着内存?这是由 redis 的过期策略来决定。

            在Redis中,当所用内存达到maxmemory上限(used_memory>maxmemory)时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制。

    Redis支持6种策略:

    • noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息(error)OOM command not allowed when used memory,此时Redis只响应读操作
    • volatile-lru:根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略
    • volatile-random:随机删除过期键,直到腾出足够空间为止
    • allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止
    • allkeys-random:随机删除所有键,直到腾出足够空间为止(不推荐)
    • volatile-ttl:根据键值对象的ttl(剩余时间(time to live,TTL) )属性,删除最近将要过期数据。如果没有,回退到noeviction策略

            LRU :Least Recently Used ,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。       

            内存溢出控制策略可以采用config set maxmemory-policy{policy}动态配置。写命令导致当内存溢出时会频繁执行回收内存成本很高,在主从复制架构中,回收内存操作对应的删除命令会同步到从节点来,来保障主从节点数据一致性,从而导致写放大的问题。

    2.2 过期策略

    Redis 服务端采用的 过期策略是 : 惰性删除 + 定期删除

    惰性删除: 

           Redis的每个库都有一个过期字典,过期字典中保存所有key的过期时间。当客户端读取一个key时会先到过期字典内查询key是否已经过期,如果key已经超过,会执行删除操作并返回空。这种策略是出于节省CPU成本考虑,但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放。

    定时删除:

            Redis内部维护一个定时任务,默认每秒运行10次过期扫描(通过 redis.conf 中通过 hz 配置 修改运行次数),扫描并不是遍历过期字典中的所有键,而是采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键:

    1. 从过期字典中随机取出 20 个键
    2. 删除这 20 个键中过期的键
    3. 如果过期键的比例超过 25% ,重复步骤 1 和 2

           为了保证扫描不会出现循环过度,一直在执行定时删除定时任务无法对外提供服务,导致线程卡死现象,还增加了扫描时间的上限,默认是 25 毫秒(即默认在慢模式下,25毫秒还未执行完,切换为块模式,模式下超时时间为1毫秒且2秒内只能运行1次,当慢模式执行完毕正常退出,会重新切回快模式)

    三、应用方更新

    1. 应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
    2. 先删除缓存,再更新数据库:这个操作有一个比较大的问题,更新数据的请求在对缓存删除完之后,又收到一个读请求,这个时候由于缓存被删除所以直接会读库,读操作的数据是老的并且会被加载进入缓存当中,后续读请求全部访问的老数据。
    3. 先更新数据库,再删除缓存(推荐)为什么不是写完数据库后更新缓存?主要是怕两个并发的写操作导致脏数据。

    四、缓存粒度

    1  通用性

           缓存全部数据比部分数据更加通用,但从实际经验看,很长时间内应用只需要几个重要的属性。

    2 占用空间

          缓存全部数据要比部分数据占用更多的空间,存在以下问题:

    • 全部数据会造成内存的浪费。
    • 全部数据可能每次传输产生的网络流量会比较大,耗时相对较大,在极端情况下会阻塞网络。
    • 全部数据的序列化和反序列化的CPU开销更大。

    3 代码维护

        全部数据的优势更加明显,而部分数据一旦要加新字段需要修改业务代码,而且修改后通常还需要刷新缓存数据。

    展开全文
  • redis缓存更新顺序的问题,先删除缓存再更新会出现问题,看网上说的最常用的方案就是Cache Aside Pattern,先更新数据库,再令缓存失效(删除缓存)。 问题来了,这里的先更新数据库再删除缓存,是等更新数据库的...
  • redis缓存部分数据库数据后,当需要更新数据库数据时,如何同步更新redis缓存内的数据了??求解,谢谢
  • 讲讲Redis缓存更新一致性。数据库是一个单位或是一个应用领域的通用数据处理系统,它存储的是属于企业和事业部门、团体和个人的有关数据的集合。数据库中的数据是从全局观点出发建立的,按一定的数据模型进行组织、...

    讲讲Redis缓存更新一致性。数据库是一个 单位或是一个应用领域的通用数据处理系统,它存储的是属于企业和事业部门、 团体和个人的有关数据的 集合。数据库中的数据是从全局观点出发建立的,按一定的 数据模型进行组织、描述和存储。其结构基于数据间的自然联系,从而可提供一切必要的存取 路径,且数据不再针对某一应用,而是面向全组织,具有整体的结构化特征。

    当执行写操作后,需要保证从缓存读取到的数据与数据库中持久化的数据是一致的,因此需要对缓存进行更新。

    因为涉及到数据库和缓存两步操作,难以保证更新的原子性。

    在设计更新策略时,我们需要考虑多个方面的问题:

    •  对系统吞吐量的影响:比如更新缓存策略产生的数据库负载小于删除缓存策略的负载
    •  并发安全性:并发读写时某些异常操作顺序可能造成数据不一致,如缓存中长期保存过时数据
    •  更新失败的影响:若某个操作失败,如何对业务影响降到最小
    •  检测和修复故障的难度: 操作失败导致的错误会在日志留下详细的记录容易检测和修复。并发问题导致的数据错误没有明显的痕迹难以发现,且在流量高峰期更容易产生并发错误产生的业务风险较大。

    更新缓存有两种方式:

    •  删除失效缓存: 读取时会因为未命中缓存而从数据库中读取新的数据并更新到缓存中
    •  更新缓存: 直接将新的数据写入缓存覆盖过期数据

    更新缓存和更新数据库有两种顺序:

    •  先数据库后缓存
    •  先缓存后数据库

    两两组合共有四种更新策略,现在我们逐一进行分析。

    并发问题通常由于后开始的线程却先完成操作导致,我们把这种现象称为“抢跑”。下面我们逐一分析四种策略中“抢跑”带来的错误。

    先更新数据库,再删除缓存

    若数据库更新成功,删除缓存操作失败,则此后读到的都是缓存中过期的数据,造成不一致问题。

    可能发生的并发错误:

    数据库讲讲Redis缓存更新一致性_数据库_数据存储_MySQL_课课家

    先更新数据库,再更新缓存

    同删除缓存策略一样,若数据库更新成功缓存更新失败则会造成数据不一致问题。

    可能发生的并发错误:

    当两个写线程发生冲突时,可以通过比较数据版本方式避免线程A写入旧的数据。

    先删除缓存,再更新数据库

    可能发生的并发错误:

    先更新缓存,再更新数据库

    若缓存更新成功数据库更新失败, 则此后读到的都是未持久化的数据。因为缓存中的数据是易失的,这种状态非常危险。

    因为数据库因为键约束导致写入失败的可能性较高,所以这种策略风险较大。

    可能发生的并发错误:

    异步更新

    双写更新的逻辑复杂,一致性问题较多。现在我们可以采用订阅数据库更新的方式来更新缓存。

    阿里巴巴开源了MySQL数据库binlog的增量订阅和消费组件 - canal。

    我们可以采用API服务器只写入数据库,而另一个线程订阅数据库 binlog 增量进行缓存更新的策略。关注java知音公众号,回复“面试题聚合”,送你一份面试题宝典

    这种策略存在和先更新数据库后删除缓存类似的并发问题:

    这个问题同样可以采用异步线程更新缓存,且写入缓存时比较数据版本的方法来解决。

    这种数据集合具有如下特点:尽可能不重复,以最优方式为某个特定组织的多种应用服务,其数据结构独立于使用它的应用程序,对数据的增、删、改、查由统一软件进行管理和控制。从发展的历史看,数据库是数据管理的高级阶段,它是由文件管理系统发展起来的。

    展开全文
  • redis 缓存更新机制

    千次阅读 2020-04-05 14:11:53
    也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。 在这里,我们讨论三种更新...
  • Redis缓存技术是现在开发常用到的技术,缓存更新也是很常见的情况,但是有时我们将缓存设置了失效时间,而我们需要更新缓存中的值但是又不想修改失效时间,希望缓存可以原定的失效时间失效。这时候就需要用到Redis的...
  • redis缓存更新策略

    千次阅读 2018-09-10 08:21:30
    (1)LRU(最近最少使用 首先淘汰最长时间未被使用的页面)/LFU(最近不常用 淘汰一定时间内不常使用的页面)/FIFO(先进先出)算法的剔除:例如maxmemory-policy ...(3)主动更新:开发控制生命周期 使用建议: ...
  • redis缓存更新的套路

    千次阅读 2018-10-14 17:31:26
    转自 酷壳-陈皓-缓存更新的套路 如有侵权请联系博主进行删除,此处仅作为学习笔记不做任何商业...看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中...
  • 第三节 redis缓存更新的套路

    万次阅读 2018-05-03 17:09:55
    转自 酷壳-陈皓-缓存更新的...试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的...
  • redis缓存更新、过期策略

    千次阅读 2019-06-02 10:55:46
    缓存过期策略: redis是单线程,收割时间也会占用线程处理时间,如果收割过于频繁,会导致读写出现卡顿 1、主库过期策略: 1.1、定时扫描 首先将每个设置了过期时间的key放到一个独立的hash中,默认每秒定时遍历这个...
  • 讲讲 Redis 缓存更新一致性

    千次阅读 2020-05-12 09:16:00
    作者:Finleywww.cnblogs.com/Finley/p/12615111.html当执行写操作后,需要保证从缓存读取到的数据与数据库中持久化的数据是一致的,因此需要对缓存进行...
  • 刷新redis缓存

    千次阅读 2019-12-25 15:51:02
    刷新redis缓存
  • SpringBoot集成Redis缓存并实现初始化用户数据到Redis缓存1、springboot集成Redis缓存1.引入依赖2.添加配置3.测试是否成功2、实现初始化用户数据到Redis缓存1.listener监听类2.实体表中需要序列化3.findById示例4....
  • 解决redis缓存穿透、redis缓存雪崩问题

    千次阅读 多人点赞 2019-08-08 16:32:04
    redis缓存雪崩 数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。 比如一个雪崩的简单过程: 1、redis集群大面积故障 2、缓存失效,但...
  • Redis缓存

    2019-12-03 17:19:25
    关于Redis缓存 Redis缓存的架构 基本缓存 多级缓存 Redis缓存的数据类型 在设计缓存的数据时,可以缓存以下类型的数据 一个数值 例如: 验证码 用户状态 如:user:{user_id}: enable 数据库记录...
  • Redis 主从 在一组从属 Redis 缓存中同步缓存刷新。 这是一项正在进行的工作,只是部分工作。
  • Redis缓存穿透、缓存雪崩问题分析

    万次阅读 多人点赞 2018-06-01 22:16:35
    redis作为缓存使用已经是司空见惯,但是使用redis后也可能会碰到一系列的问题,尤其是数据量很大的时候,经典的几个问题如下: (一)缓存和数据库间数据一致性问题 分布式环境下(单机就不用说了)非常容易出现...
  • REDIS缓存

    千次阅读 2018-08-31 16:25:24
    Redis缓存概述 Redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的key-value形式存储系统,它可以用作数据库、缓存和消息中间件。Redis内置了复制(replication)、LUA脚本、LRU事件驱动...
  • redis缓存

    2017-02-22 10:39:57
    redis是一个高性能的key-value数据库,支持内存高速缓存 我们可以用其来存储键值对数据,当然因为redis的高性能的键值对存储特性,我们也常常用...为什么Redis缓存速度这么快 首先介绍一下硬盘数据库和Redis的工作模式
  • Redis缓存的工作机制

    2021-06-08 06:59:47
    Redis:缓存的工作机制Redis缓存的工作机制缓存的特征Redis缓存处理请求Redis作为旁路缓存Redis中缓存的类型只读缓存读写缓存参考文献 Redis缓存的工作机制 Redis具有高性能的数据存取特性,广泛的应用于缓存场景,...
  • 如何不太优雅的使用Redis缓存 我们都知道使用redis来缓存我们的数据集合,如下图所示。 通常自己去缓存数据,这样的优点就是逻辑清晰,而且redis的key和value会比较规范。但是冗余代码会比较多,需要自己进行判断...
  • Redis缓存模式

    2019-12-03 17:30:47
    Redis缓存模式 Cache Aside 更新方式 先更新数据库,再更新缓存。这种做法最大的问题就是两个并发的写操作导致脏数据。如下图(以Redis和Mysql为例),两个并发更新操作,数据库先更新的反而后更新缓存,数据库...
  • Spring Boot 实践之九 Spring Boot 缓存管理 ​ 缓存是分布式系统中...​ 本章将针对Spring Boot的缓存管理进行介绍,并完成与Redis缓存中间件的整合使用。 1 Spring Boot默认缓存管理 ​ Spring Boot 管理缓存的枋心是
  • redis缓存击穿

    2021-03-17 10:22:49
    解释:我们把一些资源放在redis缓存中,用户访问资源直接从redis拿,缓存过期了同时有大量的用户同时访问资源那么就会直接访问数据库,造成数据库直接卡死。 解决办法:互斥锁;当我们用户访问缓存的时候,发现没有...
  • 使用redis 缓存策略

    2020-12-28 16:08:11
    更新数据时:先更新数据库,再删除redis中数据。 //使用redis 缓存 //1.优先从缓冲中取值 public User getCache(int userId){ String redisKey = RedisKeyUtils.getUserKey(userId); User user = (User) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,763
精华内容 45,105
关键字:

redis缓存刷新

redis 订阅