《后端程序猿 · 基于 Lettuce 实现缓存容错策略》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 近期刚转战 CSDN,会严格把控文章质量,绝不滥竽充数,如需交流,欢迎留言评论。👍

文章目录

    • 写在前面的话
    • 背景说明
    • 方案介绍
    • 具体实现
    • 总结陈词

写在前面的话

笔者所在公司由于存在大量业务场景,是借助Redis缓存实现的,因此缓存的健康状态对框架整体的影响较大。
针对这一问题,在框架封装过程中,采用了基于 Lettuce 事件总线实现的缓存容错策略和环境监测。
本篇博文鉴于此方案,展开描述,让我们絮絮道来。


背景说明

在高并发场景中,通常会引入Reids缓存机制,以此减轻数据库的查询压力,增加系统吞吐量。
例如,以Spring开发框架为例,开发者通常会选择采用@Cacheable等注解方式,便捷实现缓存的快速利用。
在传统的开发模式下,当Redis缓存宕机的时候,该注解所标注的方法会直接抛出异常,对功能调用方不太友好,并且针对缓存环境恢复的情况下,没有自动切换缓存策略的机制。开发人员往往要对单独接口进行缓存降级策略的编写,往往容易出现疏漏。开发者即使采用其他缓存客户端代码的使用方式,都不可避免的需要面对这个问题。
同时,由于Redis集群部署成本较高,部分企业并不会采用集群模式,往往不能保障Redis的高可用。
综上所述,Redis在宕机情况下的容错应对机制,是框架设计人员必须要考虑的。

【@Cacheable 技术简介】
@Cacheable 是 Spring 自带的注解,便捷操作缓存的。对于使用 @Cacheable 标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。

【关于缓存容错策略增强】
传统使用Cacheable注解Redis方法时,如果Redis服务器挂了,就直接抛出异常了,
java.net.ConnectException: Connection refused: connect
新框架对Spring的@Cacheable功能进行了增强,支持毫秒级故障自动降级与自动恢复已支持组件。


方案介绍

本方案通过自定义拓展 SpringRedisCacheManager 缓存处理器,设置不同环境的缓存处理策略,并且基于 LettuceEventBus 机制实现缓存环境监测和策略切换,以此增强单机模式下的 Redis容错性。通过这种方式,解决了传统缓存运用的弊端,开发人员可以正常使用@Cacheable,当缓存宕机的话,可以根据项目级配置,指定想要的缓存策略,比如按包装异常抛出策略、或执行原逻辑策略等。当缓存恢复的时候,会自动恢复切换到正常的缓存策略,不影响用户操作,切换不需要人工干预。当然,这一过程,对业务开发人员也是不需要特别关注的,开发人员只需要正常使用缓存场景,不需要为单独接口考虑缓存降级策略。同时,本方案支持采用延迟任务模式,不断确保缓存健康状态下缓存处理器的正确性,并做出相应响应。


具体实现

本方案自定义拓展缓存处理器,基于 Lettuce 的 EventBus 机制实现缓存环境监测和缓存策略切换。完成了对缓存宕机情况下,可以定制缓存容错策略。同时可以根据缓存环境的健康,自动切换缓存策略,增强了系统的稳定性,减少了人工运维成本。
本方案的缓存服务端不局限于Redis,缓存操作方式也不局限于Spring的@Cacheable方式,为方便理解,下文暂以这两种模式声明。
Step1、自定义缓存管理器,继承Spring自带的CacheManager,在其构造函数中,设置失败时的缓存处理器,成功时缓存处理器,当前激活缓存处理器等属性,并重写获取缓存的相关方法,同时新增同步缓存处理器的切换方法;
Step2、定义失败时缓存处理器,读取服务的项目级策略配置,示例代码如下,根据指定的缓存策略枚举,激活对应的缓存容错策略;

xxxx:
  cache:
    # degrade=自动降级
    # 当Redis服务出现故障时,不再查询Redis缓存,直接执行原有的方法逻辑
    # fail_fast=快速失败
    # 当Redis服务出现故障时,调用被标记了@Cacheable的方法将直接抛出 
    cache-fail-strategy: degrade  

Step3、同理,类似步骤2,定义成功时的缓存处理器;
Step4、在程序初始化的时候,利用Lettuce的客户端API,检查缓存当前健康状态,选择对应的缓存处理器为当前激活的缓存处理器;
Step5、在程序初始化的时候,利用Lettuce的EventBus事件总线监听机制,包含但不限于监听ConnectionActivatedEvent和ConnectionDeactivatedEvent等事件,并做出相应处理;
Step6、当监听到ConnectionDeactivatedEvent事件时,代表当前缓存状态异常,此时将触发步骤1的自定义缓存管理器的up方法,将失败时缓存处理器设定为当前激活状态,此时若逻辑执行到@Cacheable等注解方式标注的方法,将根据缓存容错策略,例如进行异常报错或直接执行原方法等;
Step7、当监听到ConnectionActivatedEvent事件时,代表当前缓存状态健康,此时将触发步骤1的自定义缓存管理器的down方法,将失败时缓存处理器设定为当前激活状态,此时若逻辑执行到@Cacheable等注解方式标注的方法,将继续正常优先从缓存加载数据;
Step8、同时,在事件监听逻辑中,利用ScheduledThreadPoolExecutor线程池的scheduleAtFixedRate方法,开启间隔延迟任务,不断检查缓存状态,确保上述缓存切换的准确性,并将结果输出日志;

缓存容错


总结陈词

上文介绍了博主所在公司采用的缓存容错策略方案,仅供参考。
从内容上看,主要是方案介绍(PS:因为是技术交底书口吻编写),有需要源代码的欢迎留言交流。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/766223.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大数据期末复习——hadoop、hive等基础知识

一、题型分析 1、Hadoop环境搭建 2、hadoop的三大组件 HDFS:NameNode,DataNode,SecondaryNameNode YARN:ResourceManager,NodeManager (Yarn的工作原理) MapReduce:Map&#xff0…

点云处理实操 点云平面拟合

目录 一、什么是平拟合 二、拟合步骤 三、数学原理 1、平面拟合 2、PCA过程 四、代码 一、什么是平拟合 平面拟合是指在三维空间中找到一个平面,使其尽可能接近给定的点云。最小二乘法是一种常用的拟合方法,通过最小化误差平方和来找到最优的拟合平面。 二、拟合步骤…

Kafka 为何如此之快?深度解析其背后的秘密

目录 前言 一、生产者 1. 异步发送 2. 多分区并行 3. 消息批量发送 4.支持消息压缩 二、存储端 1. 分区和副本 2. 页缓存 3. 磁盘顺序写入 4. 零拷贝技术 5. 稀疏索引 三、消费端 1. 消费者群组 2. 批量拉取 3. 高效的偏移量管理 4. 并行消费 总结 前言 Kafk…

观测云赋能「阿里云飞天企业版」,打造全方位监控观测解决方案

近日,观测云成功通过了「阿里云飞天企业版」的生态集成认证测试,并荣获阿里云颁发的产品生态集成认证证书。作为监控观测领域的领军者,观测云一直专注于提供统一的数据视角,助力用户构建起全球范围内的端到端全链路可观测服务。此…

SwanLinkOS首批实现与HarmonyOS NEXT互联互通,软通动力子公司鸿湖万联助力鸿蒙生态统一互联

在刚刚落下帷幕的华为开发者大会2024上,伴随全场景智能操作系统HarmonyOS Next的盛大发布,作为基于OpenHarmony的同根同源系统生态,软通动力子公司鸿湖万联全域智能操作系统SwanLinkOS首批实现与HarmonyOS NEXT互联互通,率先攻克基…

Appium adb 获取appActivity

方法一(最简单有效的方法) 通过cmd命令,前提是先打开手机中你要获取包名的APP adb devices -l 获取连接设备详细信息 adb shell dumpsys activity | grep mFocusedActivity 有时获取到的不是真实的Activity 方法二 adb shell monkey -p …

Java中反射的使用

无参构造器 方法的调用 package com.studio;import java.lang.reflect.Method;class User {private String name;/*无参构造器*/public User() {}public String getName() {return name;}public void setName(String name) {this.name name;}Overridepublic String toString…

PHP景区旅游多商户版微信小程序系统源码

解锁景区新玩法!​ 引言:一站式旅行新体验 厌倦了传统景区的单调游览?想要一次旅行就能体验多种风情?那么,“景区旅游多商户版”绝对是你的不二之选!这个创新模式将景区内多个商户资源整合,为…

C# WPF自制批注工具(方便标记重点和演示)

在教学和演示中,我们通常需要对重点进行批注,下载安装第三方工具批注显得很麻烦。本篇使用WPF开发了一个批注工具,工具小巧,功能丰富,非常使用日常免费使用,或者进行再次开发。 自制批注工具具有以下功能特…

自动驾驶水泥搅拌车在梁场的应用(下)

自动驾驶水泥搅拌车在梁场的应用(下) 北京渡众机器人科技有限公司的自动驾驶水泥搅拌车在梁场(也称为预制梁场)的应用可以带来多方面的优势和效益: 1. 自动化搅拌和运输 在梁场中,通常需要大量的混凝土搅…

查询 条件列值用notepad++批量添加单引号和逗号

参考:Notepad批量添加引号_notepad字符串统一加引号-CSDN博客 我需要批量修改数据表中某一列值指定的部分列,比如某个编号为CP0408242321001到CP0408242321101的条件。 我从数据表中把这个条件的所有编号复制出来了粘贴到了notepad里面。 如下图所示 从…

数据开源|GigaSpeech 2:三万小时东南亚多语种语音识别开源数据集发布

“Giga”一词源于“gigantic”,互联网上具有海量音频资源,但语音质量良莠不齐,高质量音频文本对数据十分稀缺且标注成本高昂,特别是在小语种领域。GigaSpeech 是一个非常成功的英文开源数据集,以 YouTube 和 Podcast 为…

读书笔记-Java并发编程的艺术-第4章(Java并发编程基础)-第1节(线程简介)

文章目录 4.1 线程简介4.1.1 什么是线程4.1.2 为什么要使用多线程4.1.3 线程优先级4.1.4 线程的状态4.1.5 Daemon 线程 Java从诞生开始就明智地选择了内置对多线程的支持,这使得Java语言相比同一时期的其他语言具有明显的优势。线程作为操作系统调度的最小单元&…

DC/AC电源模块:为智能家居设备提供恒定的电力供应

BOSHIDA DC/AC电源模块:为智能家居设备提供恒定的电力供应 DC/AC电源模块是一种常见的电源转换器,它将直流电源(DC)转换为交流电源(AC),为智能家居设备提供恒定的电力供应。在智能家居系统中&a…

Linux运维:mysql视图,用户及远程登录,用户密码的修改和破解

目 录 一、视图 二、用户 2.1 新建用户 三、创建远程登录用户test 3.1 远程登录mysql​编辑 3.1 7-1需要赋予权限 3.3 修改远程登录用户的密码 3.4 修改远程登录的用户名 3.5 删除用户:drop user lisi192.168.114.%; 四、修改用户密码 4.1 修改当前本地…

网安小贴士(3)网安协议

一、前言 网络安全协议是构建安全网络环境的基础,它们帮助保护网络通信免受各种威胁和攻击。 二、定义 网络安全协议是指在计算机网络中用于确保网络通信和数据传输安全的协议。它们定义了在网络通信过程中的安全机制、加密算法、认证和授权流程等,以保…

【论文阅读】自动驾驶光流任务 DeFlow: Decoder of Scene Flow Network in Autonomous Driving

再一次轮到讲自己的paper!耶,宣传一下自己的工作,顺便完成中文博客的解读 方便大家讨论。 Title Picture Reference and pictures paper: https://arxiv.org/abs/2401.16122 code: https://github.com/KTH-RPL/DeFlow b站视频: https://www.b…

关于 Mybatis 的开启二级缓存返回对象不一致问题

做实验报告的时候&#xff0c;跟着学习&#xff0c;发现我已经将 开启 二级缓存的 配置都配置好了&#xff0c;但是返回值地址不一致&#xff0c;说明对象不一致&#xff0c;二级缓存命中失败。 跟着流程配置&#xff1a; mybatis-config <settings><!-- 启用 myba…

SpringBoot+Thymeleaf项目重定向到另一个系统HTTPS变成HTTP

SpringBootThymeleaf项目是一个简单的单体项目&#xff0c;只有一个页面。 重定向的是前后分离&#xff0c;前端用的vue。 浏览器看到重定向后 https成了http&#xff0c;F12控制台看到是 301 Moved Permanently 单体项目最开始写法&#xff1a; response.sendRedirect(url); …

react native中使用@react-navigation/native进行自定义头部

react native中使用react-navigation/native进行自定义头部 效果示例图实例代码 效果示例图 实例代码 /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react/no-unstable-nested-components */ import React, { useLayoutEffect } from react; import…