当前位置: 首页 > 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系列产品和技术操作的视…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...

2025.6.9总结(利与弊)

凡事都有两面性。在大厂上班也不例外。今天找开发定位问题&#xff0c;从一个接口人不断溯源到另一个 接口人。有时候&#xff0c;不知道是谁的责任填。将工作内容分的很细&#xff0c;每个人负责其中的一小块。我清楚的意识到&#xff0c;自己就是个可以随时替换的螺丝钉&…...