当前位置: 首页 > news >正文

缓存归纳总结1

1. 何时需要考虑缓存一致性

缓存一致性主要在以下情况需要特别考虑:

  • 读多写少场景:当数据读取操作远多于写入时,为了提高系统性能,通常会将数据缓存起来。但一旦数据源(如数据库)中的数据发生变化,就需要确保缓存中的数据也能得到相应的更新,以保持数据的一致性。

例子:

电商平台的商品详情页: 商品信息如价格、库存量通常读取频次远高于修改频次。当库存数量因订单生成而减少时,需要确保这一变更能快速反映到缓存中,否则用户看到的可能是过时的库存信息,导致超卖问题。此时,可以通过监听数据库的更新事件,触发缓存的更新机制来维持一致。

  • 缓存击穿:大量并发请求访问刚好过期的缓存数据,如果没有合适的处理机制,可能会导致所有请求穿透到数据库,增加数据库压力。此时,通过预先加载或使用锁机制来避免击穿问题,保证缓存与数据库的一致性。

例子:

新闻网站的热点文章: 假设某篇文章突然成为热点,其缓存过期后,短时间内有大量请求涌入,若无适当处理,会导致所有请求直接查询数据库。为避免这种情况,可以采用提前刷新策略,即在缓存即将到期前,后台任务自动重新加载数据到缓存;或者使用“逻辑过期”策略,即使缓存过期,也先返回旧数据,并异步更新缓存

  • 缓存雪崩:大量缓存同时失效,可能导致所有请求直接打到数据库上,造成数据库负载过高。设置合理的缓存过期策略(如添加随机过期时间)可以减轻雪崩效应。

例子:

社交应用的动态列表: 如果所有用户的动态数据缓存都设置了相同的过期时间,当这个时间点到达,所有请求都会直接打到数据库。为减轻这种雪崩效应,可以为不同的缓存项设置随机的过期时间范围,分散缓存失效时间点,从而避免集中失效造成的压力。

2. 何时需要用分布式锁,何时本地锁就足够了

  • 分布式锁:在分布式系统中,当多个服务实例可能同时尝试修改共享资源(如数据库记录或缓存数据)时,需要使用分布式锁。例如,在高并发场景下,为了防止缓存击穿,确保只有一个线程能执行数据库查询并更新缓存,这时候分布式锁就显得尤为重要。@Cacheable注解中的sync=true就是一个简单的基于Spring Cache的同步控制,它利用了AOP代理实现类似锁的效果,以防止并发下的数据不一致,但其粒度相对粗且依赖于框架实现。

分布式锁具体例子:

  • 秒杀系统: 在电商的秒杀活动中,成千上万的用户可能同时尝试购买同一件商品,这时需要确保库存的正确扣减。通过Redis分布式锁,可以确保同一时刻只有一个请求能够执行扣减库存的操作,其他请求则等待锁释放或失败,从而维护库存的准确性和交易的公平性。
  • 本地锁:如果应用程序运行在单个JVM中,或者操作的数据仅对当前进程可见,那么使用本地锁(如Java的synchronized关键字或ReentrantLock)就足够了。本地锁可以提供更细粒度的控制,减少锁竞争带来的性能开销。但在微服务架构中,由于服务间的独立性,本地锁无法跨越服务边界,因此对于跨服务的资源访问控制,分布式锁是必要的选择。

本地锁具体例子:

  • 单体应用的数据处理: 假设有一个单体应用负责处理报表生成任务,其中包含一个方法用于统计每日销售数据。因为这个方法可能被多个线程同时调用,使用Java的synchronized关键字或ReentrantLock可以确保在任何给定时间只有一个线程能够执行该统计逻辑,防止数据错乱。

总结来说,是否采用分布式锁取决于系统的部署架构(是否为分布式系统)、并发访问的程度以及对数据一致性的严格要求。在分布式环境下,特别是在处理全局共享资源时,分布式锁是确保数据一致性和防止并发问题的有效手段。而在单机环境或服务内部操作时,本地锁即可满足需求,实现简单且效率更高。

相关文章:

  • go语言泛型Generic最佳实践 --- slices包
  • Unity 代码实现Animator开始和结束播放动画回调
  • 代码审计--一道简单的文件包含题目的多种利用方式
  • Jenkins + github 自动化部署配置
  • 二十九篇:构建未来:信息系统的核心框架与应用
  • Laravel(Lumen8) + Supervisor 实现多进程redis消息队列
  • 大一久富农机实习与商业思维学习计划
  • IS-IS DIS
  • Android:OkHttp网络请求框架的使用
  • 【二叉树】LeetCode.144:二叉树的前序遍历(小细节把握)
  • 今天说的什么好呢
  • 汇编原理(二)
  • STL库 —— unordered_set与unordered_map的封装
  • 5月23日学习记录
  • 002 CentOS 7.9 redis-7.2.5安装及配置
  • 《Java编程思想》读书笔记-对象导论
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • Android Volley源码解析
  • C++类中的特殊成员函数
  • flutter的key在widget list的作用以及必要性
  • HTTP那些事
  • LeetCode18.四数之和 JavaScript
  • magento 货币换算
  • Redis中的lru算法实现
  • Service Worker
  • 分布式事物理论与实践
  • 每天10道Java面试题,跟我走,offer有!
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 如何在 Tornado 中实现 Middleware
  • 事件委托的小应用
  • 算法---两个栈实现一个队列
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 用Visual Studio开发以太坊智能合约
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • #1015 : KMP算法
  • #java学习笔记(面向对象)----(未完结)
  • (2.2w字)前端单元测试之Jest详解篇
  • (27)4.8 习题课
  • (a /b)*c的值
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (搬运以学习)flask 上下文的实现
  • (二十四)Flask之flask-session组件
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (三)uboot源码分析
  • (四)React组件、useState、组件样式
  • (四)鸿鹄云架构一服务注册中心
  • (算法二)滑动窗口
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)VC++中ondraw在什么时候调用的
  • (转)甲方乙方——赵民谈找工作