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

架构师必备:缓存更新模式总结

大家好,我是Java烘焙师。如何更新缓存和DB、做到性能和一致性的取舍,是一个很常见的话题。下面结合笔者的经验和思考,系统性地总结一下缓存更新模式,讲透讲明白。

1、旁路缓存(cache-aside)

实现方案

  • 查询:先查缓存,查不到缓存时再查DB,并把DB内容写入缓存、设置合适的过期时间
  • 更新:先更新DB,再删缓存;做到极致则需引入延迟双删机制

之所以不是先删缓存、再更新DB,是因为在这两个操作间隙,如果有其它查询请求,则会把DB旧值写到缓存。

之所以不是先更新DB、再更新缓存,是因为写DB和缓存无法保证一致性,并且可能因为2个并发写的时序问题而把旧数据写到缓存。

之所以延迟双删,是因为在极端情况下,读线程会把DB旧值写到缓存。需要同时满足几个条件:缓存已过期,并且读线程先查询到DB旧值,然后写线程更新DB、删除缓存之后,读线程才把DB旧值写入缓存。如下图所示。

image

因此第一次删除缓存后,延迟一小段时间再删除,就能保证缓存和DB的最终一致。下图是引入了延迟双删机制的cache-aside架构图。

cache-aside查询场景:
cache-aside查询场景

cache-aside更新场景:
cache-aside更新场景

适用场景

  • 绝大部分场景

优点

  • 当数据量大时,可按需加载到缓存

缺点

  • 如果存在热点key,在失效后,会有大量查询请求穿透缓存,直接打到DB,造成DB CPU使用率飙升

旁路缓存优化:主动预刷新缓存

为了解决热点缓存失效问题,可考虑设置TTL为较长时间,并主动预刷新热点key。

根据数据量大小区分:

  • 如果数据量较大,则针对热点key,配置白名单。做得更好的话,是自动发现、并更新热点key白名单。
  • 如果数据量较小,则可以考虑全部加载到缓存中,永不过期。如:一些全局的配置数据。

根据触发刷新缓存的时机区分:

  • 定时拉取:程序自行实现,根据热点key白名单,定时查DB、并更新缓存
  • 异构数据:监听mysql变更,DB变化时触发更新缓存

更推荐异构数据的方式,好处是:缓存更新及时,并且做成通用功能之后、无需额外开发。
image

2、异步写回DB模式(write-back)

实现方案

  • 查询:只查询缓存
  • 更新:先写入缓存,然后发消息、消息链路异步写入DB,或定时任务兜底写入DB

write-back模式

适用场景

查询qps很高、极其热点的数据,优先保证性能。

场景举例:

  • 计数统计:有的页面会滚动刷新访问人次、使用人次
  • 爆品库存扣减:redis扣减库存,然后异步落库,而不是常规地操作DB扣减库存

优点

  • 支撑高qps、热点场景

缺点

  • 短期内会出现缓存和DB数据不一致情况,需要消息触发、或兜底定时任务写回DB

3、read/write through模式

实现方案

不论是cache-aside、还是write-back模式,都需要应用程序自己来控制读写缓存、DB。而read/write through模式是把控制权交给底层存储服务。

存储服务维护缓存、持久化数据,应用程序无需感知,这也是优点了。不过完全依赖于存储服务是否靠谱,实际业务场景并不常见。

4、持续优化

搭积木方式,根据实际情况做优化。

多级缓存:进一步降低缓存、DB的热点风险

  • 增加本地缓存,如caffeine
  • 或增加DB以外的异构数据,当查不到缓存时再查异构数据、查不到异构数据时最终查DB。异构数据可以是HBase、ES等

通过逻辑层面来实现生效、过期的效果,而非系统层面

  • 架构设计必须适配业务,比如通过逻辑过期解决不一致、缓存集中过期的问题,如缓存记录业务开始时间、结束时间,TTL可设置稍长些、并且通过增加随机时长来避免key集中失效。这样就能实现到时间点就变的场景,如活动开始、结束。

强一致场景,只查DB、已DB数据为准

  • 特别地,对一致性有强要求的场景:只查DB、不查缓存,以DB数据为准。如下单时查询DB里的价格,避免缓存数据非最新。

更进一步,考虑使用rocksdb,代替redis

  • rocksdb相当于是自带缓存的持久化数据库,值得专门写一篇文章介绍原理、区别,后面有空整理。

结论

  • 绝大部分场景,使用旁路缓存模式(cache-aside)。更进一步,对部分热点key做主动预刷新,可监听DB变更、或定时刷新。
  • 高qps、极热key场景,使用异步写回DB模式(write-back),优先保证性能,可接受短时间内DB与缓存不一致。
  • 持续优化:
    • 增加多级缓存、异构数据,来降低缓存、DB的热点风险
    • 通过逻辑层面来实现生效、过期的效果
    • 强一致场景,只查DB、已DB数据为准

延伸阅读:笔者之前写的缓存相关文章,欢迎围观。

  • 架构师必备:本地缓存原理和应用
  • Spring cache源码分析

相关文章:

架构师必备:缓存更新模式总结

大家好,我是Java烘焙师。如何更新缓存和DB、做到性能和一致性的取舍,是一个很常见的话题。下面结合笔者的经验和思考,系统性地总结一下缓存更新模式,讲透讲明白。 1、旁路缓存(cache-aside) 实现方案查询:先查缓存,查不到缓存时再查DB,并把DB内容写入缓存、设置合适的…...

为什么不能在try-catch中捕获子线程的异常 ?

一、基础概念...

sensitive-word 敏感词性能提升14倍优化全过程 v0.28.0 - 实践

sensitive-word 敏感词性能提升14倍优化全过程 v0.28.0 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New"…...

2025 PHP 开发者必看得 25 个容易犯的常见错误 90% 的开发者都踩过

2025 PHP 开发者必看得 25 个容易犯的常见错误 90% 的开发者都踩过 前言 PHP 发展到今天,新特性层出不穷,最佳实践也在不断更新。写出干净、高效、好维护的代码,对每个 PHP 开发者来说都很重要。 这篇文章总结了 PHP 开发中最容易踩的坑,以及对应的解决方案。 不管你是刚入…...

一款带有AI功能的markdown工具

大家好,我是晓凡。 写在前面 关注晓凡的同学都知道,晓凡是一名程序员。 平常有空的时候会写写博客,将一些技术干货或者踩过的坑分享给大家。 和我一样写技术博客的小伙伴都知道,平常素材来源太杂:脑子里突然而来的灵感 群里的一张梗图 随手的一张截图 读书看到的一段文字 …...

45万亿!中国智驾的新风口来了

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087 添加图片注释,不超过 140 字(可选)2025年L4智驾场景化应用加速发展,亿欧汽车研究院认为2035年中国L4级别及以上智能驾驶…...

apache poi 导出繁琐的excel表格

apache poi 导出繁琐的excel表格pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; fon…...

Ubuntu Server SSH 连接

使用 SSH 连接(最推荐的方式) 这是最专业、最稳定的方式,特别适合服务器环境:一、在 Ubuntu Server 中确保 SSH 服务已安装并运行: sudo apt update sudo apt install -y openssh-server sudo systemctl enable ssh sudo systemctl start ssh 二、获取虚拟机的 IP 地址: …...

利用竞态条件轻松上传Web Shell

本文详细介绍了如何通过竞态条件漏洞上传PHP Web Shell,使用普通Burp Intruder工具而非Turbo Intruder,包含完整的攻击步骤、PHP代码分析和实战配置,适合初学者理解文件上传漏洞的利用方式。通过竞态条件上传Web Shell(简易方法) 方法特点 本攻击使用普通Burp Intruder而非…...

我亲眼目睹我上海的家长朋友陷进去了

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 354695541004908701我发现在网上很多人都在说不要内卷了,不要卷了,因为我们快被自己人卷死了。我这人天生迟钝,后知后觉的,所以总是赶不上时…...

蔚小理的辅助驾驶,谁最拉跨?

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087汽车诞生以来,从来没试过像现在这样,一台车可以在买回来之后,不花一分钱,表现就能获得提升。而且还不只是那些贵的车型,就…...

C 语言的 printf() 函数

概述 printf() 的作用: Print formatted output to the standard output stream. printf() 的函数原型: int printf( const char *format, argument1, argument2, ... );printf() 函数的基本格式: printf(格式字符串, 待打印项列表);或者写为: printf(格式字符串, 待打印项 1,…...

【GitHub每日速递 250915】3 个宝藏开源项目:超长语音合成、算法学习库、自托管软件导航,开发者速收

原文:【GitHub每日速递 250915】3 个宝藏开源项目:超长语音合成、算法学习库、自托管软件导航,开发者速收 VibeVoice:挑战传统TTS,最长90分钟多角色语音合成神器来袭! VibeVoice 是一个长对话文本转语音模型的开源项目。简单讲,它能将连续的文本内容自然地转换成语音,支…...

C 语言头文件

两种写法: #include <stdio.h> // 编译系统在系统头文件所在目录搜索 #include "stdlib.h" // 编译系统首先在当前的源文件目录中查找 stdlib.h,找不到的话,再转向系统头文件所在目录搜索引用系统头文件时,使用两种形式都可以,但是 #include <> 的…...

AFL++环境搭建

第 1 步:更新软件源并安装基本工具 首先更新软件包列表 sudo apt update 升级现有软件包 sudo apt upgrade -y 安装基本编译工具(包括gcc) sudo apt install -y build-essential 安装Python3和相关工具 sudo apt install -y python3 python3-dev python3-pip 创建python符号…...

晚安

cai~一定是做梦,不然还能是什么,对不对? 总之就是梦到一年前的自己对我说话: 第一句:变菜了 第二句:本来就挺菜 然后开始大笑,前车窗上晃动着一双眼睛,小,但是不瞎。...

读人形机器人12体育领域

读人形机器人12体育领域1. 体育领域 1.1. 在体育竞技这个不断挑战人类极限的领域,人形机器人正以教练和训练助手的身份进入 1.2. 由金属材料、代码和AI技术打造的机器人,正在革新运动员的训练方式、恢复过程和竞技表现 2. 个性化训练计划 2.1. 追求卓越的运动表现既是一门科学…...

【QT】C++基础

前言 目前打算一周内学习QT的基本使用,从此篇"C++基础"文章开始记录分享学习经验。 C++及其各种定义C++是面向对象的,什么是面向对象,什么是面向过程? 举例 计算a+b的值: C语言,直接计算a+b;C++,先将a+b封装,封装到类里面形成一个方法,然后再通过这个类去…...

安全研究者的MCP服务器宝典:BugBounty工具集锦

本资源库汇集了多个专为漏洞赏金、渗透测试和信息安全研究设计的MCP服务器,提供一站式安全工具整合,帮助安全专业人员高效开展授权安全测试和研究工作。BugbountiesMCP 一个专为漏洞赏金、渗透测试和信息安全研究设计的Model Context Protocol (MCP) 服务器综合列表资源库。 …...

Unity的VisualStudio工程链接不同步、显示异常处理方法

前段时间,在某次更新项目工程后,原本好好的VS工程,变得不认Unity_Editor的宏、Using显示不正确了,一般来说,这个在Unity使用中,很常见,通用解决办法是:在Unity的Extrenal Tool里有一个Regenerate的按钮,直接重新生成解决方案。 关了Unity工程,到路径里把sln和proj这些…...

Java 高性能与可维护性实战:从语言特性到工程化全链路

一、设计目标:为什么“快”和“稳”必须同时追 在真实业务里,“快”(吞吐、延迟)与“稳”(可维护、可演进)往往拉扯。高性能带来的复杂度不应成为维护负担,而可维护的抽象也不应牺牲关键路径。可落地的目标是:可预测性能:接口在 SLA 下延迟稳定,P95/P99 可控。渐进式…...

二叉树的递归遍历

前中后序的递归遍历 递归算法的三要素确定递归函数的参数和返回值:要确定哪些参数是递归过程中需要处理的,需要处理的就在递归函数里面加上这个参数;然后确定每次返回的递归值是什么; 确定终止条件:必须写终止条件;如果不写终止条件就会栈溢出; 确定单层递归的逻辑: 确…...

我的大学成长与规划

大家好,我是李思慧,一名计算机科学与技术专业的大二学生。生活里,我是个爱折腾的人,喜欢在文字的世界里遨游,也热衷于用视频和图片记录生活、表达创意。 在信工分团委宣传部当干事到现在的部长,是我成长很快的一段时光。从最开始跟着学长学姐学习写各种活动和通知的推文,…...

【笔记】拉格朗日插值

拉格朗日插值的推导对于一个 \(n\) 次多项式 \(f(x) = \sum_{k = 0}^n a_kx^k\),我们只要知道它在 \(n+1\) 个不同点处的取值,就可以进一步解出它的系数 但使用高斯消元法的时间复杂度是 \({\cal O}(n^3)\) 的,如果我们只是想知道这个多项式在某一点 \(x\) 处的值,希望有复…...

自定义渲染管线(Unity Cocos)

参考链接: 团结引擎 - 手册: 在自定义渲染管线中创建简单渲染循环 可定制渲染管线(Deprecated) | Cocos Creator Custom SRP - Custom Render Pipeline | 三叔的数字花园 自定义渲染管线_Unity SRP从零搭建一套图形渲染管线_UWA学堂(翻译的Catlik,还收费) Unity Custom S…...

这是一个测试

这是一个测试...

文献阅读 | Survey of Hallucination in Natural Language Generation

问题描述 本文主要讲了NLG中的幻觉现象 幻觉定义:模型生成不忠实于源内容或无意义的文本 幻觉分类:内在幻觉(矛盾、完全错误的)、外在幻觉(无法被验证) 幻觉危害:隐私泄露 成因:评估指标:统计 metric:基于 n-gram 重叠,如 PARENT(结合源和目标)、Knowledge F1(对…...

技术 | LLaMA Factory微调记录重修版

之前投的那篇教程我自己回看一遍都不太搞得明白,从新梳理一遍 1. 云服务器准备 恒源云 (gpushare.com) 配置建议:GPU: RTX 3090 (24GB) 或 RTX 4090 (24GB) 系统: Ubuntu 20.04/22.04 存储: 至少 50GB 空间2. 环境检查与初始化 # 检查GPU状态 nvidia-smi# 检查系统信息 df -h…...

支付中心的钱包类业务应该怎么设计

钱包类业务在支付行业里有一些比较固定的模式(无论是支付宝余额宝、微信零钱,还是 Stripe Balance / Paytm Wallet),基本设计目标是:余额和资金安全:必须有严格的账实一致、幂等和防篡改能力。高并发读写:充值/消费/退款频繁,要求快速的扣减和回滚能力。清晰的流水:任…...

MySQL索引浅析

NORMAL:普通索引,仅用于加速查询,允许字段值重复。 UNIQUE:唯一索引,不仅能加速查询,还会强制字段值的唯一性(即该字段下的值不能重复)。 FULLTEXT:全文索引,用于全文搜索场景(如文章内容的关键词检索)。 SPATIAL:空间索引,用于地理空间数据类型(如 GEOMETRY、P…...

WF 2025 游记

第一次出国旅行因为错误在 EC-Final 显神威成功出线,我得以以 RCDS 随队人员的身份作为 ICPC Guest 参与 2025 ICPC World Final Baku. Day -5 ​ 被然叔拉到苏州给软件杯打工。 ​ 出站时落雨大暴,翻书包发现没有雨伞,凌乱中就看到然叔开着辆绿色 SUV 过来接我,到了苏州大…...

17.时间处理

17.时间处理日期和时间是日常编程常用的功能之一。如果没有日期和时间,会导致很多功能无法实现,例如日志记录、定时任务、时间延迟等。Go标准库提供了操作日期和时间的方法。在提到时间,还需要注意不同地区的时间会不一样,所以这里还需要考虑到不同时区、不同历法等带来的影…...

[MCP][02]快速入门MCP开发

快速入门MCP Server和MCP Client 开发,以及Client集成LLM前言 很多文档和博客都只介绍如何开发MCP Server,然后集成到VS Code或者Cursor等程序,很少涉及如何开发MCP Host和MCP Client。如果你想要在自己的服务中集成完整的MCP功能,光看这些是远远不够的。所以本文及后续的M…...

numpy入门

numpy 基本属性 import numpy as np arr = np.arange(15).reshape((3,5)) print(arr) # [[ 0 1 2 3 4],[ 5 6 7 8 9],[10 11 12 13 14]] print(type(arr)) # 类型 <class numpy.ndarray> print(arr.shape) # 形状元组 (3, 5) print(arr.ndim) # 维度 2 print(arr…...

【simpleFOC】一个电机如何模拟不同旋钮的手感反馈?

原文链接:https://mp.weixin.qq.com/s?__biz=MzU1NjEwMTY0Mw==&mid=2247597033&idx=2&sn=e92f8f1dec8b363aa209788354f8fa64&chksm=fad1130bfafd0b9af53b0f110e354d8772f6c5a0d98735690d1c0c75d0c3c75785ea1041ea1a&scene=27概述simpleFOC可以实现对各种…...

第一周作业2

我叫陈俊杰,今年19岁,目前是一名计算机相关专业的学生。很高兴能在博客园与大家分享我的学习与生活经历。 兴趣爱好 我热爱运动,尤其是羽毛球、篮球、游泳和攀岩。这些运动不仅让我保持了健康的体魄,也培养了我的团队协作能力和坚持不懈的精神。此外,我也喜欢探索新技术,…...

第一次课堂作业

大家好!我是一名数据科学与大数据技术专业的大三学生。如果用一句话形容现在的自己,那就是 “正处在专业技能积累的爬坡期,一边为过去的基础不扎实查漏补缺,一边对未来的技术方向满怀期待”。这篇博客想和大家聊聊我的故事、我的技能现状,以及我为接下来的学习和未来发展制…...

[高可用/负载均衡] Ribbon LoadBalancer: 开源的客户端式负载均衡框架

0 序言某项目上,原先为自建的数据库集群提供了负载均衡IP服务器(简称: ELB IP Server),客户端的数据库请求URL都统一走ELB IP。但随着业务量的增长,识别到一个严峻的现实:其一,考虑到未来的业务增长情况,云厂商提供的 ELB IP Server 云服务的入网带宽必将完全无法满足本项…...

梦话周记

忘记是哪天了。 傍晚,暗蓝色的天空,水雾,朦胧的光晕。 此时的天空与以往理解的深邃可谓是一点关系都没有,它的深邃不再来自于天空,而是来自于大海。什么地方是深蓝色的,湿润的,广阔的?海洋。 其实气体与液体有很多相似之处,它们都有浮力,都是流体。我们是不是也生活在…...

【电机控制】无刷电机结构阐述---磁极数、槽数

一、磁极数P与槽数N 1.磁极数P 定义:转子上磁极的数量,既转子上磁钢的数量,磁钢均匀的排列在转子上磁铁必定是NS极成对使用,所以极数必然是偶数。 2.槽数N 定义:定子铁芯的槽数量,既定子上的电磁铁极数量,每一个槽上都饶有一组线圈,如上图有12个槽,所以是12N电机由于无…...

金刚怒目是我哭

金刚怒目是我哭是你们太不善良,还是我太不正常马喽马基米退圈了。我下载的its my cry没了,my mujuca也只有前三集 这个可以说是我的入坑作 确实有点刻意 反正不是日常向 即使现在看来也是无可厚非的 但还是爆了 我应该说戾气很重吗 杂食党,,,理中客,和稀泥 说不出话 雨...

nginx使用默认端口80作为服务端口

背景:http默认端口是80,配置nignx.conf,希望服务url直接输入ip不用输入端口 给server配置80以及加default_server ,老是报错,后面发现是因为 include /etc/nginx/sites-enabled/*; 这个配置的server段占用了80 解决办法:把默认配置/etc/nginx/sites-available/default 里…...

机器学习和推荐算法顶级会议和期刊

在机器学习(ML)与推荐系统(Recommender Systems)领域,CIKM 和 TKDE 是信息检索、数据挖掘及数据库领域的重要学术载体,二者分别以会议(CCF A 类)和期刊(CCF A 类)形式存在,覆盖 “推荐算法”“用户行为分析”“知识图谱与推荐融合” 等核心方向,是该领域研究者发表…...

java使用mysql

用jdbc操作mysqlhttps://www.runoob.com/java/java-mysql-connect.htmlmysql8之前和之后的连接配置有差异。实际使用时,一般还需要个功能,就是连接池。这个springboot自带了,是hikari。hikari初始化的时候,也需要配置mysql的连接参数,所以一般都是在这里设置的。https://w…...

2025年医疗行业API安全最佳实践与深度案例分析:从理论到全面落地

2025年医疗行业API安全最佳实践与深度案例分析:从理论到全面落地医疗API安全是保障患者隐私和医疗数据安全的关键环节。医疗机构、信息化服务商和安全厂商需遵循GB/T《数据接口安全风险监测方法》要求,建立覆盖"发现-监测-处置"的全生命周期防护体系。以金华市中心…...

2026 NOI 做题记录(二)

推荐阅读:D、N、W、Y、Z、AB、AC、AD、AE、AFContest Link \(\text{By DaiRuiChen007}\)A. [ARC194E] Swap 0^X and 1^Y (3) Problem Link 删掉所有的串 \(0^x\) 以及 \(1^y\),每次操作不会跨过里面的连续段,因此剩下的串必定相同。 取出每个连续段,任意两个 \(0\) 连续段在…...

lc1027-最长等差数列

难度:中等(后期)题目描述给定一个数组,计算最长等差数列的长度示例 输入:nums = [3,6,9,12] 输出:4 解释:3 6 9 12输入:nums = [9,4,7,2,10] 输出:3 解释:4 7 10输入:nums = [20,1,15,3,10,5,8] 输出:4 解释:20 15 10 5题解思路:DPf(i,j): 以 i 结尾,公差为 j 结…...

13

#include <math.h>int main() { int n; scanf("%d", &n); while (n--) {int l, r;scanf("%d %d", &l, &r); int y_max = (int)sqrt(r);//算l的平方根,然后向上取整并强制转换为整数, y >= lint y_min = (int)ceil(sqrt(l));int c…...

np.zeros函数

np.zeros 是 NumPy 库中的一个非常常用的函数,它的作用是创建一个指定形状和数据类型的新数组,并用 0 来填充所有元素。 np.zeros 的基本用法 函数的完整签名是 numpy.zeros(shape, dtype=float, order=C)。shape:你想要创建的数组的形状。可以是一个整数(用于一维数组)或…...

Langchain之让LLM拥有记忆

langchain的Memory 如果AI有记忆,我们就不需要手动维护一个储存消息历史的列表 让LLM拥有记忆的方法有很多,我更喜欢使用的方法是以下方案,其优点是灵活度比较高 from langchain.memory import ConversationBufferMemory from langchain_core.prompts import ChatPromptTemp…...