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

【Java】在高并发场景下,保证 Redis 缓存一致性的几种方案

在高并发场景下,保证 Redis 缓存一致性是一个常见的挑战。以下是几种常见的解决方案及其优缺点,以及相应的代码示例。

1. Cache Aside Pattern (旁路缓存模式)

原理
  • 读取数据时,先读缓存,如果缓存没有命中,再从数据库读取,并将数据写入缓存。
  • 更新数据时,先更新数据库,然后删除缓存。
优点
  • 简单易实现,适用于读多写少的场景。
  • 更新时立即删除缓存,能有效防止缓存数据不一致。
缺点
  • 存在短暂的不一致性窗口期。
  • 并发更新时可能导致缓存被频繁删除。
代码示例
public class CacheAsidePattern {private RedisTemplate<String, Object> redisTemplate;private DatabaseService databaseService;public CacheAsidePattern(RedisTemplate<String, Object> redisTemplate, DatabaseService databaseService) {this.redisTemplate = redisTemplate;this.databaseService = databaseService;}public Object get(String key) {Object value = redisTemplate.opsForValue().get(key);if (value == null) {synchronized (this) {value = redisTemplate.opsForValue().get(key);if (value == null) {value = databaseService.getFromDb(key);if (value != null) {redisTemplate.opsForValue().set(key, value);}}}}return value;}public void update(String key, Object value) {databaseService.updateDb(key, value);redisTemplate.delete(key);}
}

2. Read-Through Cache (读穿缓存)

原理
  • 读取数据时,如果缓存未命中,由缓存系统从数据库加载数据,并将其缓存。
优点
  • 自动加载数据到缓存,简化应用程序代码。
  • 减少缓存未命中带来的性能损失。
缺点
  • 实现复杂,需要自定义缓存加载逻辑。
  • 写操作没有明确处理,需结合其他策略保证一致性。
代码示例
public class ReadThroughCache {private RedisTemplate<String, Object> redisTemplate;private DatabaseService databaseService;public ReadThroughCache(RedisTemplate<String, Object> redisTemplate, DatabaseService databaseService) {this.redisTemplate = redisTemplate;this.databaseService = databaseService;}public Object get(String key) {Object value = redisTemplate.opsForValue().get(key);if (value == null) {value = databaseService.getFromDb(key);if (value != null) {redisTemplate.opsForValue().set(key, value);}}return value;}
}

3. Write-Through Cache (写穿缓存)

原理
  • 更新数据时,先更新缓存,再更新数据库。
优点
  • 数据始终保持一致性,适合高一致性要求的场景。
  • 简化读取逻辑,数据始终在缓存中。
缺点
  • 写操作性能较低,因为每次写操作都涉及数据库更新。
  • 如果数据库更新失败,缓存也会被污染。
代码示例
public class WriteThroughCache {private RedisTemplate<String, Object> redisTemplate;private DatabaseService databaseService;public WriteThroughCache(RedisTemplate<String, Object> redisTemplate, DatabaseService databaseService) {this.redisTemplate = redisTemplate;this.databaseService = databaseService;}public Object get(String key) {return redisTemplate.opsForValue().get(key);}public void update(String key, Object value) {redisTemplate.opsForValue().set(key, value);databaseService.updateDb(key, value);}
}

4. Write-Behind Cache (异步写缓存)

原理
  • 更新数据时,先更新缓存,然后异步地将数据写入数据库。
优点
  • 写操作性能较高,适用于写多读少的场景。
  • 减少了直接写数据库的延迟。
缺点
  • 实现复杂,需保证异步操作的可靠性。
  • 存在数据丢失的风险,需要处理异步操作失败的情况。
代码示例
public class WriteBehindCache {private RedisTemplate<String, Object> redisTemplate;private DatabaseService databaseService;private ExecutorService executorService;public WriteBehindCache(RedisTemplate<String, Object> redisTemplate, DatabaseService databaseService) {this.redisTemplate = redisTemplate;this.databaseService = databaseService;this.executorService = Executors.newFixedThreadPool(10);}public Object get(String key) {return redisTemplate.opsForValue().get(key);}public void update(String key, Object value) {redisTemplate.opsForValue().set(key, value);executorService.submit(() -> {databaseService.updateDb(key, value);});}
}

5. Consistent Hashing (一致性哈希)

原理
  • 通过一致性哈希算法,将缓存数据均匀分布到不同的缓存节点上。
优点
  • 提高缓存的可扩展性和容错性。
  • 数据分布均匀,减少单点压力。
缺点
  • 实现复杂,需要引入一致性哈希算法。
  • 适用于分布式缓存场景,对于单机缓存无显著优势。
代码示例
import java.util.SortedMap;
import java.util.TreeMap;public class ConsistentHashing {private TreeMap<Integer, RedisTemplate<String, Object>> hashRing = new TreeMap<>();private int numberOfReplicas;public ConsistentHashing(int numberOfReplicas, List<RedisTemplate<String, Object>> redisTemplates) {this.numberOfReplicas = numberOfReplicas;for (RedisTemplate<String, Object> redisTemplate : redisTemplates) {addNode(redisTemplate);}}private void addNode(RedisTemplate<String, Object> node) {for (int i = 0; i < numberOfReplicas; i++) {int hash = hash(node.toString() + i);hashRing.put(hash, node);}}public RedisTemplate<String, Object> getNode(String key) {if (hashRing.isEmpty()) {return null;}int hash = hash(key);if (!hashRing.containsKey(hash)) {SortedMap<Integer, RedisTemplate<String, Object>> tailMap = hashRing.tailMap(hash);hash = tailMap.isEmpty() ? hashRing.firstKey() : tailMap.firstKey();}return hashRing.get(hash);}private int hash(String key) {return key.hashCode() & 0x7fffffff;}
}

每种策略都有其适用的场景和特点,具体选择哪种方案需要根据实际的业务需求和系统特性来决定。

相关文章:

【Java】在高并发场景下,保证 Redis 缓存一致性的几种方案

在高并发场景下&#xff0c;保证 Redis 缓存一致性是一个常见的挑战。以下是几种常见的解决方案及其优缺点&#xff0c;以及相应的代码示例。 1. Cache Aside Pattern (旁路缓存模式) 原理 读取数据时&#xff0c;先读缓存&#xff0c;如果缓存没有命中&#xff0c;再从数据…...

GaussDB数据库的备份与恢复

1.逻辑备份-gs_dump gs_dump是一款用于导出数据库相关信息的工具&#xff0c;支持导出完整一致的数据库对象&#xff08;数据库、模式、表、视图等&#xff09;数据&#xff0c;同时不影响用户对数据库的正常访问。 备份sql语句 gs_dump是openGauss用于导出数据库相关信息的工…...

03-02-Vue组件之间的传值

前言 我们接着上一篇文章 03-01-Vue组件的定义和注册 来讲。 下一篇文章 04-Vue&#xff1a;ref获取页面节点–很简单 父组件向子组件传值 我们可以这样理解&#xff1a;Vue实例就是一个父组件&#xff0c;而我们自定义的组件&#xff08;包括全局组件、私有组件&#xff09;…...

昂达固态硬盘数据恢复方法:全面解析与操作指南

在数字化时代&#xff0c;数据已经成为我们生活和工作中不可或缺的一部分。而固态硬盘&#xff08;SSD&#xff09;由于其读写速度快、抗震性强等优点&#xff0c;慢慢取代了传统的机械硬盘&#xff0c;成为我们存储数据的主要选择。然而&#xff0c;即便再先进的存储设备&…...

C++的红黑树

目录 基本概念 插入结点的颜色 判断性质是否破坏 调整方式 u为g的右孩子 u存在且为红 u存在且为黑 u不存在 结论 红黑树结点定义 代码实现 基本概念 1、红黑树是一种特殊的二叉搜索树&#xff0c;每个结点会增加一个存储位表示结点的颜色&#xff08;红或黑&#x…...

Keras深度学习框架第二十九讲:在自定义训练循环中应用KerasTuner超参数优化

1、简介 在KerasTuner中&#xff0c;HyperModel类提供了一种方便的方式来在可重用对象中定义搜索空间。你可以通过重写HyperModel.build()方法来定义和进行模型的超参数调优。为了对训练过程进行超参数调优&#xff08;例如&#xff0c;通过选择适当的批处理大小、训练轮数或数…...

手机App收集个人信息,用户是否有权拒绝?

其实过度收集个人信息这件事&#xff0c;在APP上随处可见&#xff0c;泛滥成灾。 前两天有个不疼不痒的小软件“小鸡词典”&#xff0c;因为收集个人信息受到了处罚。 小鸡词典因划分为工具类APP过度收集隐私&#xff08;手机号、地理位置定位&#xff09;、不同意政策不能用…...

云下到云上,丽迅物流如何实现数据库降本50% | OceanBase案例

在2024年3月20日的首场OceanBase数据库城市行活动中&#xff0c;专注于物流及供应链解决方案的丽迅物流的架构师阳磊&#xff0c;围绕“OB Cloud在丽迅物流的实践”这一主题&#xff0c;进行了精彩的演讲。本文为此次演讲的内容回顾。 在丽迅物流&#xff08;Lesoon Logistics…...

STM32无源蜂鸣器播放音乐

开发板&#xff1a;野火霸天虎V2 单片机&#xff1a;STM32F407ZGT6 开发软件&#xff1a;MDKSTM32CubeMX 文章目录 前言一、找一篇音乐的简谱二、确定音调三、确定节拍四、使用STM32CubeMX生成初始化代码五、代码分析 前言 本实验使用的是低电平触发的无源蜂鸣器 无源蜂鸣器是…...

【云原生】kubernetes中的认证、权限设置---RBAC授权原理分析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…...

【Python设计模式04】策略模式

策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以互相替换。策略模式让算法的变化不会影响使用算法的客户端&#xff0c;使得算法可以独立于客户端的变化而变化。…...

私域用户画像分析:你必须知道的3个关键点!

在互联网时代的变革中&#xff0c;私域流量成为越来越多企业的关注焦点。而了解私域用户画像是建立精准营销策略的关键一步。 今天&#xff0c;就给大家分享私域用户画像分析的三个关键点&#xff0c;让大家都能更好地进行用户画像分析。 1、市场需求 理解市场需求是把握用户…...

【MATLAB源码-第74期】基于matlab的OFDM-IM索引调制系统不同频偏误码率对比,对比OFDM系统。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM-IM索引调制技术是一种新型的无线通信技术&#xff0c;它将正交频分复用&#xff08;OFDM&#xff09;和索引调制&#xff08;IM&#xff09;相结合&#xff0c;以提高频谱效率和系统容量。OFDM-IM索引调制技术的基本思想…...

优于其他超导量子比特数千倍!猫态量子比特实现超过十秒的受控比特翻转时间

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨娴睿/慕一 排版丨沛贤 深度好文&#xff1a;2000字丨8分钟阅读 摘要&#xff1a;量子计算公司Alice & Bob和QUANTIC团队&#xff08;国立巴黎高等矿业学院PSL分校、巴黎高等师范学院和…...

QtXlsx库编译使用

文章目录 一、前言二、Windows编译使用2.1 用法①&#xff1a;QtXlsx作为Qt的附加模块2.1.1 检验是否安装Perl2.1.2 下载并解压QtXlsx源码2.1.3 MinGW 64-bit安装模块2.1.4 测试 2.2 用法②&#xff1a;直接使用源码 三、Linus编译使用3.1、安装Qt5开发软件包&#xff1a;qtbas…...

LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107

一、题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[…...

WIFI国家码设置的影响

记录下工作中关于国家码设置对WIFI的影响&#xff0c;以SKYLAB的SKW99和SDZ202模组为例进行说明。对应到日常&#xff0c;就是我们经常提及手机是“美版”“港版”等&#xff0c;它们的wifi国家码是不同的&#xff0c;各版本在wifi使用中遇到的各种情况与下面所述是吻合的。 现…...

2024年软考高项-信息系统管理师介绍-备考-考试内容-通过攻略

介绍 以下是计算机软件考试的资格设置&#xff0c;本文说的是高级资格中的信息系统项目管理师(简称"高项")&#xff0c;是比较热门和好考的选择&#xff0c;与中级的"系统集成项目管理工程师"有大部分的知识重叠交叉&#xff0c;中级考了"系统集成项…...

Python知识点复习

文章目录 Input & OutputVariables & Data typesPython字符串重复&#xff08;字符串乘法&#xff09;字符串和数字连接在一起print时&#xff0c;要强制类型转换int为str用input()得到的用户输入&#xff0c;是str类型&#xff0c;如果要以int形式计算的话&#xff0c…...

GeoScene产品学习视频收集

1、易智瑞运营的极思课堂https://www.geosceneonline.cn/learn/library 2、历年易智瑞技术公开课视频资料 链接&#xff1a;技术公开课-易智瑞信息技术有限公司&#xff0c;GIS/地理信息系统&#xff0c;空间分析-制图-位置智能-地图 3、一些关于GeoScene系列产品和技术操作的视…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...