Redis 的缓存策略(二)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis 的缓存策略(二)

🥩 缓存更新的三个策略

 内存淘汰: redis底层的内存淘汰机制,无需我们自己维护,当内存不足时自动淘汰部分数据,下次查询时更新缓存。这种机制的优点是维护成本极低,但是缺点也很明显,由于淘汰数据的不确定性导致很难保证数据的一致性

 超时剔除: 向redis中添加缓存数据的时候设置TTL时间,到期后自动删除缓存,下次查询时更新缓存。这种机制维护成本不是很高,但是数据一致性同样无法做到很高的保证,因为设置之后数据的有效期就固定了,但是更新时间不固定,若是数据在超时剔除之前发生更新然后查询,得到的仍是更新之前的数据

 主动更新: 使用代码在修改数据库的同时更新缓存。这种策略能够保证很高的数据一致性,但是伴随而来的就是更高的维护成本,要在每一个更改语句后面加上redis缓存更新


 具体使用哪种策略取决于该业务对数据一致性的需求:一致性需求不高的话,可以使用内存淘汰策略。一致性需求较高的话,可以使用主动更新加上超时剔除策略,保证了较高的一致性

🥩 主动更新策略的三种方案

 代码(Cache Aside Pattern):最直接的一种方案,使用代码在修改数据库的同时更新缓存

 服务(Read/Warite Through Pattern):将redis缓存与数据库整合为一个服务,由这个服务来维护数据的一致性,在更新数据库时只需要调用该服务即可,无需关心服务底层的业务逻辑,类似于封装。但是市面上没有现成的服务可以使用,自己封装这么一个服务也很复杂,所以说这种方案可用性很差

 写回(Write Behind Caching Pattern):所有数据库的CRUD操作都在redis缓存中完成,由另外一个独立的线程异步的将缓存中的数据持久化到数据库中,以此来保证数据的最终一致。这种方案有个很大的好处,那就是极大地减少了对数据库的操作,如果主线程在另一个线程两次持久化之间对redis中的数据操作多次,数据库中只会执行最后一次操作,而不是也操作多次。但是也有坏处,那就是如果还没等到另一个线程持久化数据库,此时redis缓存发生宕机,缓存大多数在内存中,此时发生宕机就会导致缓存中的数据消失,数据库中的数据就与宕机前redis中的数据不一致


 综上所述,虽然Cache Aside Pattern方案是最复杂的一个,但是他也同样是最可靠的一个,于是我们选择它来进行接下来的代码学习


主动更新策略注意项

 数据库发生更新的时候直接删除缓存中的该数据,而不是跟着更新缓存,因为如果发生连续修改多次的情况,更新缓存的话更新次数等于数据库的更新次数;如果是删除缓存数据的话就只需要删除一次,下一次查询直接从数据库中查询再写入缓存。

 删除缓存数据和数据库操作应该保证原子性,也就是说删除缓存数据操作和数据库操作应该同时成功或者同时失败,那么该如何实现呢?单体式系统中,可以通过将两个操作放在一个事务中来完成;分布式系统中可以利用TCC等分布式事务方案来实现

 删除缓存数据操作和数据库操作的先后顺序是什么? 应该是先写数据库再删除缓存,原因是这种方式发生线程安全性问题的可能较小


🥩 主动更新的代码实现

controller层前端交互


/**
 * 更新商铺信息
 * @param shop 商铺数据
 * @return 无
 */
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
    // 写入数据库
    return shopService.update(shop);
}


 需要server的update方法,创建接口和实现类完成业务逻辑代码编写。主动更新+超时剔除的策略就只有两步,那就是在写缓存的时候设置超时时间,更新数据库之后删除缓存


// 数据库中存在写入redis的时候设置超时时间
stringRedisTemplate.opsForValue().set(RedisConstants.CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop), RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);
/**
 * 更新商铺信息
 * @param shop  商铺信息
 * @return 前端返回数据
 */
@Override
@Transactional
public Result update(Shop shop) {
    if (shop.getId() == null) {
        return Result.fail("店铺id不能为空");
    }
    // 更新数据库
    updateById(shop);
    // 删除缓存
    stringRedisTemplate.delete(RedisConstants.CACHE_SHOP_KEY + shop.getId());
    // 返回
    return Result.ok();
}

image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
10天前
|
缓存 NoSQL 中间件
Redis,分布式缓存演化之路
本文介绍了基于Redis的分布式缓存演化,探讨了分布式锁和缓存一致性问题及其解决方案。首先分析了本地缓存和分布式缓存的区别与优劣,接着深入讲解了分布式远程缓存带来的并发、缓存失效(穿透、雪崩、击穿)等问题及应对策略。文章还详细描述了如何使用Redis实现分布式锁,确保高并发场景下的数据一致性和系统稳定性。最后,通过双写模式和失效模式讨论了缓存一致性问题,并提出了多种解决方案,如引入Canal中间件等。希望这些内容能为读者在设计分布式缓存系统时提供有价值的参考。感谢您的阅读!
Redis,分布式缓存演化之路
|
1月前
|
存储 缓存 NoSQL
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
|
1月前
|
缓存 NoSQL 关系型数据库
云端问道21期实操教学-应对高并发,利用云数据库 Tair(兼容 Redis®)缓存实现极速响应
本文介绍了如何通过云端问道21期实操教学,利用云数据库 Tair(兼容 Redis®)缓存实现高并发场景下的极速响应。主要内容分为四部分:方案概览、部署准备、一键部署和完成及清理。方案概览中,展示了如何使用 Redis 提升业务性能,降低响应时间;部署准备介绍了账号注册与充值步骤;一键部署详细讲解了创建 ECS、RDS 和 Redis 实例的过程;最后,通过对比测试验证了 Redis 缓存的有效性,并指导用户清理资源以避免额外费用。
|
2月前
|
缓存 监控 NoSQL
Redis经典问题:缓存穿透
本文详细探讨了分布式系统和缓存应用中的经典问题——缓存穿透。缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致大量请求直接落到数据库上,可能引发数据库崩溃或性能下降。文章介绍了几种有效的解决方案,包括接口层增加校验、缓存空值、使用布隆过滤器、优化数据库查询以及加强监控报警机制。通过这些方法,可以有效缓解缓存穿透对系统的影响,提升系统的稳定性和性能。
|
2月前
|
存储 消息中间件 设计模式
缓存数据一致性策略如何分类?
数据库与缓存数据一致性问题的解决方案主要分为强一致性和最终一致性。强一致性通过分布式锁或分布式事务确保每次写入后数据立即一致,适合高要求场景,但性能开销大。最终一致性允许短暂延迟,常用方案包括Cache-Aside(先更新DB再删缓存)、Read/Write-Through(读写穿透)和Write-Behind(异步写入)。延时双删策略通过两次删除缓存确保数据最终一致,适用于复杂业务场景。选择方案需根据系统复杂度和一致性要求权衡。
75 0
|
2月前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
188 85
|
2月前
|
缓存 API C#
C# 一分钟浅谈:GraphQL 中的缓存策略
本文介绍了在现代 Web 应用中,随着数据复杂度的增加,GraphQL 作为一种更灵活的数据查询语言的重要性,以及如何通过缓存策略优化其性能。文章详细探讨了客户端缓存、网络层缓存和服务器端缓存的实现方法,并提供了 C# 示例代码,帮助开发者理解和应用这些技术。同时,文中还讨论了缓存设计中的常见问题及解决方案,如缓存键设计、缓存失效策略等,旨在提升应用的响应速度和稳定性。
56 13
|
2月前
|
NoSQL 算法 Redis
redis内存淘汰策略
Redis支持8种内存淘汰策略,包括noeviction、volatile-ttl、allkeys-random、volatile-random、allkeys-lru、volatile-lru、allkeys-lfu和volatile-lfu。这些策略分别针对所有键或仅设置TTL的键,采用随机、LRU(最近最久未使用)或LFU(最少频率使用)等算法进行淘汰。
77 5
|
2月前
|
NoSQL 安全 Redis
redis持久化策略
Redis 提供了两种主要的持久化策略:RDB(Redis DataBase)和AOF(Append Only File)。RDB通过定期快照将内存数据保存为二进制文件,适用于快速备份与恢复,但可能因定期保存导致数据丢失。AOF则通过记录所有写操作来确保数据安全性,适合频繁写入场景,但文件较大且恢复速度较慢。两者结合使用可增强数据持久性和恢复能力,同时Redis还支持复制功能提升数据可用性和容错性。
73 5
|
3月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
69 5