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

缓存及其不一致

        在实际开发过程中,一般都会遇到缓存,像本地缓存(直接在程序里搞个map也可以,但是可能会随着数据的增长出现OOM,建议使用正经的本地缓存框架,因为自己实现淘汰策略啥的挺费劲的)、分布式缓存,简单记录以下自己对这两方面的理解。

        本地缓存就是将数据缓存在当前应用程序本地,它速度快,易于管理,但是它无法跨多节点共享,在集群环境中会出现不一致的问题。多个本地缓存之间的数据可能不一致。

        分布式缓存就是将数据存储到多个节点的内存中,这些节点可以再不同服务器甚至不同的地理位置上。分布式缓存可以支持多个程序共享数据,提高系统的可伸缩性和可用性,但是成本比较高,考虑的地方也比较多,如数据一致性和故障恢复等问题。

        从上面不难看出来缓存有个共性,那就是缓存的一致性问题,在分布式的系统中,只能在CA中进行平衡,根据具体得到业务甚至数据特性进行平衡。

      本地缓存

        首先在选择上,现在的缓存框架多的很,Caffeine、Guava等,但是spring cache默认是支持Caffeine的

        启用本地缓存呢,就是为了减少网络连接(数据库、redis这都要的),有些数据频繁访问,而且这些数据在其他应用模块中不会使用或很少使用且这些数据很少会有所变动,如行政区划、行业信息、纳税人识别号以及一些系统内的数据。这种就适合放到本地内存里。

        但是本地内存有个问题,就是在集群环境里,多份数据的存储会造成内存的浪费,这点需要考虑到,但是世上安有两全法,只能是在,两者之间做权衡,选性能还是选成本。

        一旦要涉及到本地内存的一致性问题,那这问题就麻烦了,解决办法也不是没有,但一到实际中就等于是脱裤子放屁了,比如:数据库或者redis里弄个版本号,用本地缓存之前先看看版本号是否一致,这就和使用本地缓存的初衷不一致了啊,我就是想减少数据库访问或者redis连接的,结果现在还要再去访问,我为了什么呢?干嘛不直接用redis啊?

        所以本人认为一旦要考虑本地缓存的一致性问题了,那就说明你这个缓存没必要要了。

      分布式缓存

        分布式缓存解决了各个应用之间的一致性的问题,但它还是会存在与数据库的一致性问题。

        而这个一致性问题的解决方式有很多,具体要根据业务以及数据的特性来确定。

        先说说数据不一致产生的原因,拿redis举例,在逻辑中有两个操作,更新数据库与刷新缓存(有时候缓存信息很多,比如我存了一件商品的信息,里面有商品价格,有商品的库存,如果是更新的话,两个线程并发,首先都先后获取到了缓存的信息,都进行了修改,然后保存的时候一次提交,那这时候肯定有一个是没更新进去的),这两个操作都有可能失败,但是数据库可以开启事务,失败了就回滚,但是redis可没有回滚这一说,所以要想保证数据和缓存的一致性,大家就要想尽办法来解决这个问题。

        ①开启事务

         如果要求强一致性,缓存更新失败可以让数据库事务回滚。先执行逻辑更新数据库,然后刷新缓存。这样会有三种情况:1、都成功,皆大欢喜;2、数据库刷新成功,缓存刷新失败,数据库回滚,缓存未变,数据库也未变;3、数据库失败,直接回滚;

       ②刷新数据,操作缓存

        系统并发没那么高或者对一致性要求不高的可以采用更新缓存,删除的缓存可以消除并发操作缓存导致的数据不一致的问题。这种情况下如果更新缓存失败,可以根据业务的需求来确定是否采取重试机制或者采用MQ消息进行异步修改策略。

        ③延迟双删

        具体步骤是:删除缓存,刷新数据库,延迟1-2秒,删除数据库。

        刷新缓存失败的可能性比删除的可能性大很多,所以采用删除缓存的方式。并发高的情况下还要考虑到刷新缓存也可能会导致数据不一致的问题,所以采用删除的方式。第二次的删除是防止在第一次删除缓存,数据还未落到数据库的时候有线程查缓存没查到直接拿的数据库,之后又将数据缓存;虽然这第二次删除可能会导致删除掉正确数据,但是顶多会发生一次cache miss。

        总的来说,针对分布式缓存与数据库的一致性问题,要根据具体情况来进行分析,并发量大且要求一致性高的数据就延迟双删,至于之后可能产生的缓存击穿问题,那就是另外的问题了,缓存击穿有缓存击穿的解决方案。如果并发量不大的情况下,直接刷数据库然后再刷缓存(删或者刷看具体情况),如果失败了可以采用重试机制或者异步MQ消息重试的方式进行解决。

        没有啥完美方案,只能找最适合业务的方案

                 

相关文章:

缓存及其不一致

在实际开发过程中,一般都会遇到缓存,像本地缓存(直接在程序里搞个map也可以,但是可能会随着数据的增长出现OOM,建议使用正经的本地缓存框架,因为自己实现淘汰策略啥的挺费劲的)、分布式缓存&…...

Leetcode 有效的数独

这段代码解决的是 验证一个数独是否有效 的问题,其算法思想是基于 规则校验和状态记录。具体思想如下: 算法思想 核心目标: 检查每个数字在 同一行、同一列 和 同一个 3x3 子格 中是否重复。 状态记录: 使用 3 个布尔二维数组分别…...

《Java核心技术 卷I》用户界面中首选项API

首选项API 在桌面程序中,通常都会存储用户首选项,如用户最后处理的文件、窗口的最后位置等。 利用Properties类可以很容易的加载和保存程序的配置信息,但有以下缺点: 有些操作系统没有主目录概念,很难为匹配文件找到…...

Android 中的 Zygote 和 Copy-on-Write 机制详解

在 Android 系统中,Zygote 是一个关键的进程,几乎所有的应用进程都是通过它 fork(派生)出来的。通过 Zygote 启动新进程的方式带来了显著的性能优势,这得益于 fork 操作和 Linux 中的 Copy-on-Write(COW&am…...

【人工智能】从零开始用Python实现逻辑回归模型:深入理解逻辑回归的原理与应用

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 逻辑回归是一种经典的统计学习方法,用于分类问题尤其是二分类问题。它通过学习数据的特征和目标标签之间的…...

推荐一款功能强大的光学识别OCR软件:Readiris Dyslexic

Readiris Dyslexic是一款功能强大的光学识别OCR软件,可以扫描任何纸质文档并将其转换为完全可编辑的数字文件(Word,Excel,PDF),然后用你喜欢的编辑器进行编辑。该软件提供了一种轻松创建,修改和签名PDF的完整解决方法&…...

Python爬虫----python爬虫基础

一、python爬虫基础-爬虫简介 1、现实生活中实际爬虫有哪些? 2、什么是网络爬虫? 3、什么是通用爬虫和聚焦爬虫? 4、为什么要用python写爬虫程序 5、环境和工具 二、python爬虫基础-http协议和chrome抓包工具 1、什么是http和https协议…...

css-50 Projects in 50 Days(3)

html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>旋转页面</title><link rel"sty…...

另外一种缓冲式图片组件的用法

文章目录 1. 概念介绍2. 使用方法2.1 基本用法2.2 缓冲原理3. 示例代码4. 内容总结我们在上一章回中介绍了"FadeInImage组件"相关的内容,本章回中将介绍CachedNetworkImage组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的CachedNetwo…...

字节青训-小C的外卖超时判断、小C的排列询问

目录 一、小C的外卖超时判断 问题描述 测试样例 解题思路&#xff1a; 问题理解 数据结构选择 算法步骤 最终代码&#xff1a; 运行结果&#xff1a; 二、小C的排列询问 问题描述 测试样例 最终代码&#xff1a; 运行结果&#xff1a; ​编辑 一、小C的外卖超时判断…...

PHP 伪静态详解及实现方法

概述 在现代 Web 开发中&#xff0c;URL 的设计对用户体验和搜索引擎优化&#xff08;SEO&#xff09;至关重要。动态 URL 虽然功能强大&#xff0c;但往往显得冗长且不友好。伪静态&#xff08;URL 重写&#xff09;技术通过将动态 URL 转换为静态样式&#xff0c;不仅提高了…...

Spring Boot 简单预览PDF例子

目录 前言 一、引入依赖 二、使用步骤 1.创建 Controller 处理 PDF 生成和预览 2.创建预览页面 总结 前言 使用 Spring Boot 创建一个生成 PDF 并进行预览的项目&#xff0c;你可以按以下步骤进行。我们将使用 Spring Boot、Thymeleaf、iText 等技术来完成这个任务。 一、引入…...

【魔珐有言-注册/登录安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…...

LabVIEW 使用 Snippet

在 LabVIEW 中&#xff0c;Snippet&#xff08;代码片段&#xff09; 是一个非常有用的功能&#xff0c;它允许你将 一小段可重用的代码 保存为一个 图形化的代码片段&#xff0c;并能够在不同的 VI 中通过拖放来使用。 什么是 Snippet&#xff1f; Snippet 就是 LabVIEW 中的…...

单片机_day3_GPIO

目录 1. 灯如何才能亮 1.1原理图 1.2 二极管 1.3 换了一个灯和原理图 ​编辑 1.4 三极管 1.4.1 NPN型三极管 1.4.2 PNP型三极管 2. 基本概念 3. 输入 3.1 浮空输入 3.2 上拉输入 3.3 下拉输入 3.4 模拟输入 4. 输出 4.1 推挽输出 4.2 开漏输出 如何让开漏输出…...

Python小游戏24——小恐龙躲避游戏

首先&#xff0c;你需要安装Pygame库。如果你还没有安装&#xff0c;可以通过以下命令安装&#xff1a; 【bash】 pip install pygame 【python】代码 import pygame import random # 初始化Pygame pygame.init() # 设置屏幕尺寸 screen_width 800 screen_height 600 screen …...

Python 的多态笔记

Python的多态实际是通过instance 实现的 class Person:def __init__(self, name,age):self.name nameself.age agedef feed_pet(self,pet):#isinastance(obj,类)-->判断obj,是不是这个类的对象&#xff0c;或者判断obj是不是该类的子类的对象if isinstance(pet, Pet):sel…...

go module使用

go module介绍 go module是go官⽅⾃带的go依赖管理库,在1.13版本正式推荐使⽤ go module可以将某个项⽬(⽂件夹)下的所有依赖整理成⼀个 go.mod ⽂件,⾥⾯写⼊了依赖的版本等 使⽤ go module之后我们可不⽤将代码放置在src下了 使⽤ go module 管理依赖后会在项⽬根⽬录下⽣成…...

c ++零基础可视化——数组

c 零基础可视化 数组 一些知识&#xff1a; 关于给数组赋值&#xff0c;一个函数为memset&#xff0c;其在cplusplus.com中的描述如下&#xff1a; void * memset ( void * ptr, int value, size_t num );Sets the first num bytes of the block of memory pointed by ptr to…...

CVE-2024-2961漏洞的简单学习

简单介绍 PHP利用glibc iconv()中的一个缓冲区溢出漏洞&#xff0c;实现将文件读取提升为任意命令执行漏洞 在php读取文件的时候可以使用 php://filter伪协议利用 iconv 函数, 从而可以利用该漏洞进行 RCE 漏洞的利用场景 PHP的所有标准文件读取操作都受到了影响&#xff1…...

Turms开发者定制指南:如何基于源码进行二次开发

Turms开发者定制指南&#xff1a;如何基于源码进行二次开发 【免费下载链接】turms &#x1f54a;️ The worlds most advanced open source instant messaging engine for 100K~10M concurrent users https://turms-im.github.io/docs 项目地址: https://gitcode.com/gh_mir…...

ElevenLabs Starter计划实战指南(新手必看的4步激活+2次配额翻倍技巧)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs Starter计划的核心定位与适用边界 ElevenLabs Starter 计划是面向开发者、内容创作者及小型团队推出的免费语音合成入门方案&#xff0c;旨在以零门槛方式提供高质量、低延迟的文本转语音&…...

中文知识管理利器:本地化部署与向量检索实践指南

1. 项目概述&#xff1a;一个面向中文用户的知识管理利器 最近在折腾个人知识库&#xff0c;发现了一个挺有意思的开源项目&#xff0c;叫 RomeoSY/zh-knowledge-manager 。乍一看名字&#xff0c;你可能觉得这又是一个“知识管理”工具&#xff0c;市面上不是有 Notion、Ob…...

常见404 500错误解析

一、常见404 500错误解析浏览器&#xff1a;用户发起请求的入口&#xff0c;地址栏输入 URL、AJAX 请求都从这里发。服务器&#xff1a;本质就是一台电脑&#xff0c;Tomcat 在这里负责接收请求、分发处理。前端层&#xff1a;存放静态页面&#xff0c;处理页面渲染、用户交互…...

W4A4量化技术:OSC框架如何实现高效LLM部署

1. OSC框架&#xff1a;硬件高效的W4A4量化革命在大型语言模型(LLM)部署领域&#xff0c;4-bit量化(W4A4)正成为突破算力瓶颈的关键技术。传统8-bit量化虽已成熟&#xff0c;但当我们将精度压缩至4-bit时&#xff0c;激活张量中的异常值(Outliers)会像"黑洞"般吞噬有…...

ECA:编辑器无关的AI编程伴侣,统一配置多模型与编辑器

1. 项目概述&#xff1a;一个编辑器无关的AI编程伴侣如果你和我一样&#xff0c;每天大部分时间都泡在编辑器里&#xff0c;那你肯定也经历过这种场景&#xff1a;面对一段复杂的业务逻辑&#xff0c;或者一个陌生的API&#xff0c;你希望有个“懂行”的伙伴能立刻给你解释、重…...

移动网络安全盲区:Windows PC成恶意软件主要源头与防御策略

1. 一个被忽视的真相&#xff1a;移动网络中的“隐形杀手”如果你和我一样&#xff0c;长期关注网络安全&#xff0c;尤其是移动安全领域&#xff0c;那你可能已经习惯了各种关于安卓恶意软件激增、iOS漏洞被利用的警报。媒体头条也总是被“史上最危险手机病毒”这样的标题占据…...

20 鸿蒙LiteOS信号量原理实战:信号量作用、MAX_COUNT含义、线程同步源码解析

鸿蒙LiteOS信号量原理实战&#xff1a;信号量作用、MAX_COUNT含义、线程同步源码解析 一、前言 本文基于小凌派 RK2206鸿蒙LiteOS标准示例代码&#xff0c;从零讲解LiteOS内核信号量核心概念&#xff1a;为什么需要信号量、信号量能干什么、MAX_COUNT参数真实含义&#xff0c…...

Excel数据同步ERP/CRM太麻烦?一个Python脚本搞定多系统自动填充(基于GoBot)

Excel数据同步ERP/CRM太麻烦&#xff1f;一个Python脚本搞定多系统自动填充&#xff08;基于GoBot&#xff09; 每次月底看着财务同事在ERP系统里逐条录入Excel数据&#xff0c;市场部同事又在CRM里重复同样的操作&#xff0c;这种低效场景你一定不陌生。数据在不同系统间的孤岛…...

ctf show web 入门46

这道题目是上一题的升级版&#xff0c;过滤条件变得更加苛刻了。我们来分析一下新增的限制以及应对方案。 代码审计与变化 相比之前&#xff0c;正则过滤 preg_match 新增了以下内容&#xff1a; [0-9]&#xff1a;禁止使用任何数字。这意味着 $IFS$9 这种绕过方式失效了。 \$&…...