下线 MyBatis 二级缓存后,如何用 Spring Cache + Redis 构建安全可靠的缓存体系?

Java面试核心:JVM、并发、Spring、MySQL与Redis实战解析 在Java后端开发领域,掌握核心原理是构建高性能、高可用系统的基石。从JVM内存模型与垃圾回收机制,到并发编程中的锁优化与线程安全,这些基础概念共同构成了现代Java应用的运行框架。理解其原理不仅能帮助开发者进行有效的性能调优和问题排查,更能提升系统设计的深度与广度。例如,通过分析JVM的GC日志和内存快照,可以精准定位线上OOM问题的根源;而深入理解Spring框架的三级缓存机制和事务传播行为,则是解决复杂依赖和保证数据一致性的关键。在实际应用场景中,无论是利用Redis缓存应对高并发查询,还是基于MyS 阅读详情

下线 MyBatis 二级缓存后,如何用 Spring Cache + Redis 构建安全可靠的缓存体系?

背景:在我的高并发服务中,曾长期依赖 MyBatis 二级缓存。但随着业务复杂度上升,其跨节点不一致、缓存穿透难控、序列化不可定制等问题日益突出。最终,我决定彻底下线 MyBatis 二级缓存,全面启用 Spring Cache + Redis 方案。

但切换不是简单加个注解就完事。必须确保:

  • 缓存底层是 Redis(而非内存或 Ehcache);
  • 序列化方式安全、可读、支持多态;
  • 写操作与 DB 强一致,尤其在乐观锁场景下不能翻车。

下面是我的完整实践。


一、核心配置:RedisCacheConfig.java

首先要明确:Spring Cache 是抽象层,必须绑定到 Redis 实现。以下是我在生产环境中稳定运行半年以上的配置:

package com.xiaochuan.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
@EnableCaching // 启用 Spring Cache 注解
public class RedisCacheConfig {

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 构建默认缓存配置:1 小时过期,禁止缓存 null 值
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
                .defaultCacheConfig()
                .entryTtl(Duration.ofHours(1))                          // 默认 TTL:1 小时
                .disableCachingNullValues()                             // 不缓存 null,防缓存穿透需另做处理
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new StringRedisSerializer()))   // Key 使用 String 序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer())); // Value 使用带类型信息的 JSON

        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(connectionFactory)
                .cacheDefaults(defaultCacheConfig)
                .transactionAware() // 与 Spring 事务同步:事务回滚时避免脏缓存写入
                .build();
    }

    /**
     * 配置支持泛型和子类反序列化的 Jackson JSON 序列化器
     * - 启用默认类型信息(写入 @class 字段)
     * - 允许反序列化为真实子类,而非 LinkedHashMap
     */
    private RedisSerializer<Object> jackson2JsonRedisSerializer() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 激活类型信息写入(非 final 类会写入 @class 字段),支持多态反序列化
        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );

        return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
    }
}

✅ 为什么这么配?

配置项作用风险规避
Jackson 序列化生成可读 JSON,支持子类避免 JDK 原生序列化的安全漏洞和版本兼容灾难
禁用 null 缓存不缓存 null 值防止无效 key 被长期缓存,掩盖“用户不存在”的真实语义
transactionAware()缓存写入绑定 Spring 事务避免“事务回滚但缓存已更新”的脏数据问题
Key 用 String 序列化Redis key 为纯字符串便于运维查看、监控、手动清理

💡 穿透处理建议:disableCachingNullValues() 后,缓存穿透需另解——我用 短 TTL(如 30 秒)的占位符 或 布隆过滤器 拦截无效 ID。


二、UserService:缓存与 DB 的一致性实践

配置只是基础,真正的挑战在写操作的一致性。以下是我的完整 UserService,特别关注乐观锁 + 缓存更新的协同。

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    // 查:命中缓存则跳过 DB
    @Cacheable(value = "user:profile", key = "#userId", unless = "#result == null")
    public User getUserById(Long userId) {
        return userMapper.selectWithVersion(userId);
    }

    // 改:先更新 DB,再用返回值更新缓存
    @CachePut(value = "user:profile", key = "#user.id")
    public User updateUser(User user) {
        if (userMapper.updateWithVersion(user) == 0) {
            throw new OptimisticLockException("用户数据已被他人修改,请重试");
        }
        // 注意:此处 user 必须包含有效 version!
        return user;
    }

    // 删:先删 DB,再删缓存
    @CacheEvict(value = "user:profile", key = "#userId")
    public void deleteUser(Long userId) {
        userMapper.deleteById(userId);
    }
}

🔑 关键细节:乐观锁与 version 字段的生命周期

在我的系统中:

  • version 是数据库乐观锁字段,由系统维护;
  • 前端 DTO 中不包含 version(对客户端透明);
  • Java 实体 User 仍保留 version 字段,供 MyBatis 使用。

因此,不能直接将前端 DTO 转为 User 实体后调用 updateUser!否则 version 为 null,乐观锁失效。

✅ 正确调用方式(Service 层封装):
// Controller 层
@PostMapping("/user/{id}")
public User update(@PathVariable Long id, @RequestBody UserUpdateDTO dto) {
    return userService.updateUserFromDTO(id, dto);
}

// Service 层
public User updateUserFromDTO(Long userId, UserUpdateDTO dto) {
    // 1. 从 DB 加载完整实体(含当前 version)
    User user = userMapper.selectWithVersion(userId);
    if (user == null) throw new UserNotFoundException("用户不存在");

    // 2. 仅更新业务字段(保留 version)
    user.setName(dto.getName());
    user.setEmail(dto.getEmail());

    // 3. 调用内部更新方法(此时 user.version 有效)
    return updateUser(user); // 触发 @CachePut
}

💡 ORM 回填保障:

  • 如果你用 MyBatis-Plus(带 @Version 注解),更新成功后 user.version 会自动回填为新值;
  • 如果你用 原生 MyBatis,建议在 updateUser 中更新后重新查询,确保缓存对象与 DB 完全一致:
@CachePut(value = "user:profile", key = "#userId")
public User updateUser(User user) {
    if (userMapper.updateWithVersion(user) == 0) {
        throw new OptimisticLockException("数据已被修改,请重试");
    }
    // 安全兜底:重新加载(适用于无自动 version 回填的场景)
    return userMapper.selectWithVersion(user.getId());
}

三、依赖与监控建议

📦 必要依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Jackson 已由 starter-data-redis 间接引入 -->

🌟 命名规范:缓存名用 user:profile 而非 userCache,便于在 Redis 中按业务域隔离,也方便通过 KEYS user:* 监控或清理。


四、血泪教训:别让“自动”变成“失控”

Spring Cache 注解看似简单,但每一行 @Cacheable 都隐含了一致性承诺。我的原则是:

  • 写操作必须同步维护缓存:用 @CachePut 更新,@CacheEvict 删除;
  • 缓存 key 必须稳定无副作用:用 #userId(标量),别用 #user.name(可能变);
  • 高敏感数据慎用缓存:如余额、权限等,要么强制短 TTL,要么走强一致读路径(绕过缓存);
  • 务必开启 transactionAware():否则事务回滚时缓存已更新,数据永久不一致!

✅ 终极口诀(建议背诵)

配置用 RedisCacheManager,序列化选 Jackson;
事务感知要开启,空值缓存需谨慎。
更新必带 version,先查后改是铁律;
DTO 无 version,实体加载要牢记。
Key 用参数别用对象,命名规范带前缀;
自动缓存虽省力,一致性责任在你肩!


这套方案已在我司多个高并发核心服务(日均千万级请求)稳定运行半年以上,零缓存不一致事故。


关注我,从零开始构建基础 IT 设施。
—— 旷野说

SpringBoot+微信小程序企业级项目实战:网络安全知识管理平台全栈开发 在构建现代企业级应用时,SpringBoot作为后端服务框架,以其“约定大于配置”的理念和强大的自动配置能力,极大地简化了开发与部署流程,成为Java领域快速开发的首选。其原理在于通过内嵌Web服务器和起步依赖,实现了开箱即用的微服务架构。结合MyBatis作为持久层框架,开发者可以在灵活编写SQL与对象关系映射之间找到平衡,这对于需要复杂查询和性能优化的业务场景至关重要。这种技术组合的价值在于,它能高效支撑起一个稳定、可维护且易于扩展的业务系统。典型的应用场景包括企业内部管理系统、在线教育平台以及各类需要 阅读详情

相关推荐

Java面试题深度解析:从虚拟线程到分布式锁的实战指南

在Java技术生态中,掌握核心原理与工程实践是开发者构建稳定、高效系统的基石。理解JVM内存模型、垃圾回收机制及并发编程原理,是进行性能调优和解决线上问题的关键。这些基础概念直接关联到微服务、高并发等现代应用场景的技术价值。例如,Java 19引入的虚拟线程(Virtual Threads)革新了高并发I/O密集型应用的编程模型,它能以极低的资源开销管理海量并发连接,显著提升系统吞吐量。而在分布式系统设计中,确保数据一致性与服务可靠性是核心挑战,分布式锁便是解决资源互斥访问的常见方案。本文以一份精心设计的J

weixin_34406086的博客 358

缓存基本理论

缓存的设计思想在架构设计中十分常见。比如我们每天用的操作系统,都有系统缓存、用户缓存。磁盘有磁盘缓存区、CPU有CPU缓存区。再比如,在我们常用的经典框架中,也经常使用到缓存,Spring有IoC缓存,MyBatis有一级缓存、二级缓存。可以说缓存无处不在。

阿巴阿巴 1716

Java面试题

JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。JRE(Java Runtime Environment),Java运行环境。JDK(Java Development Kit),Java开发工具包。如果重写了equals方法,equals比较的是对象的内容。如果没有重写equals,equals就相当于==;对于引用类型,==比较的是堆中内存对象的地址;对于基本类型,==比较的是栈中的值;

IAtlantiscsdn的博客 348

Redis 入门

本文全面介绍了Redis技术体系,从基础概念到高级应用场景,主要内容包括: NoSQL基础 对比关系型数据库的局限性 四大分类:文档型、键值型、列族型、图型数据库 Redis作为高性能键值数据库的特点 Redis核心功能 五种数据结构:String、List、Set、ZSet、Hash 持久化机制:RDB快照与AOF日志 主从复制与哨兵机制实现高可用 Cluster集群实现数据分片 开发实践 Java客户端操作指南 SpringBoot整合方案 MyBatis二级缓存实现 缓存穿透/击穿/雪崩解决方案

weixin_51689532的博客 4613

钉钉Java面经及参考答案

TCP 三次握手建立连接的核心目标是双向确认双方发送、接收能力,同步通信序列号,协商初始窗口大小,防止历史过期连接报文干扰新连接。第一次握手,客户端主动向服务端发送 SYN 报文,携带客户端随机生成的初始序列号 ISN,客户端状态变更为 SYN_SENT,目的是告知服务端客户端具备发送数据的能力。第二次握手,服务端收到 SYN 报文后,回复 SYN+ACK 报文,其中 ACK 确认号为客户端 ISN+1,同时携带服务端自身随机初始序列号,服务端进入 SYN_RCVD 状态,代表服务端确认收到客户端报文,且自

大模型大数据攻城狮的专栏 238

104报文解析工具

可选择包含报文的文本文件或日志文件进行解析,可选择按条数范围或时间范围,输出结果可以在报文解析显示区,也可以输出到文件。可以对文本内容的报文文件进行高级分析,包括遥信遥测等通讯数据的具体信息,通讯帧的统计,通讯次数的统计,各种错误的分析,报文的定位功能,传输的文件具体内容等。输入完成后点击工具栏的解析报文按钮或使用右键菜单的解析就可以对报文进行解析。在报文输入区输入待解析报文并解析后,解析结果就显示在报文解析显示区和报文定位展示区及报文定位条目区。当有多条报文解析后,可以通过报文列表树具体定位某条报文。

XZHOUMIN的博客 5952

java八股文极速版

时间和空间的权衡 值越高空间开销小但是增加了查找开销服务于从Key映射到index的Hash算法,在性能和内存的使用上取平衡,实现一个尽量均匀分布的Hash函数,选取16,是通过位运算的方法进行求取的。线程安全:当多线程执行同一段程序的时候,如果发生了和预期结果不一致的情况,就是线程不安全的,如果和预期结果一致就是线程安全的,可以加锁解决(把并行运行的线程变成串行化执行)。1.加锁 利用Synchronized或者ReenTrantLock来对不安全对象进行加锁。

PassionAnytime的博客 382

深入浅出卡尔曼滤波器算法

深入浅出讲解卡尔曼滤波器的工作原理及其公式推导,讨论卡尔曼滤波器的核心公式所代表的意义及个人的理解。

m0_37835056的博客 1366

Java+SSM与Flask混合架构的智能招聘问答系统设计

现代招聘系统正从单向信息传递向双向互动演进,其中智能问答技术成为提升用户体验的关键。基于自然语言处理(NLP)的推荐算法能精准匹配求职者问题与企业回答,而混合架构设计则兼顾系统稳定性与AI功能扩展性。Java领域的SSM框架(Spring+SpringMVC+MyBatis)提供成熟的RBAC权限控制和事务管理能力,配合Python Flask轻量灵活的NLP处理模块,形成优势互补的技术方案。这种架构特别适合需要处理复杂业务逻辑又需集成AI功能的场景,如招聘问答、智能客服等。通过TF-IDF和协同过滤算法实

weixin_33853827的博客 261

开源onlyoffice编译完整过坑版

onlyoffice 编译过坑完整版;

sHImart 4551

IMU卡尔曼滤波方法详细介绍

本文介绍了基于IMU和卡尔曼滤波的状态估计方法。系统采用9维状态向量(位置、速度、加速度计零偏),通过牛顿运动学建立状态方程,并利用外部位置观测进行校正。详细推导了状态转移矩阵和控制输入矩阵的形式,阐述了预测和更新的计算步骤。同时说明了过程噪声Q和观测噪声R的设置原则,其中Q反映模型不确定性,R取决于传感器精度。该方法可有效融合IMU测量与外部观测数据,实现位置、速度和偏置的联合估计。

haing2019的博客 758

MuleSoft企业级AI编排:让大模型真正听懂ERP和CRM

AI编排(AI Orchestration)是将大语言模型(LLM)融入企业核心业务系统的关键范式,其本质不是简单调用API,而是通过强契约、可治理、低延迟的集成层,解决LLM‘泛化能力’与企业系统‘刚性元数据契约’之间的根本冲突。技术原理上依赖元数据驱动连接器、运行时数据编织(DataWeave)与混合部署安全边界,实现自然语言到结构化业务指令的精准翻译。其核心价值在于提升AI输出的准确性、合规性与可审计性,支撑客服响应提速、合同生成自动化、智能补货等高ROI场景。本文聚焦MuleSoft Anypoin

weixin_34178244的博客 465

Windows 10/11 安装 HYSPLIT 气象模型全攻略(附必备工具包下载清单)

本文提供了一份详尽的Windows 10/11系统下HYSPLIT气象模型安装与配置全攻略。指南涵盖了从核心认知、必备工具包(Tcl/Tk、ImageMagick)下载,到分步安装、环境变量设置及首次运行验证的完整流程,旨在帮助研究者和学生高效部署这一用于大气轨迹模拟与污染物扩散分析的专业工具。

weixin_28335283的博客 612

实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑

商品详情服务,要求:商品基础信息走缓存,减少 DB 查询;典型:AI 只贴注解,忽略 AOP 代理、key 设计、缓存穿透/击穿/过期、序列化、同步刷新,本地单测正常,上线后缓存脏数据、命中率异常、雪崩。如果业务在事务中,@CacheEvict / @CachePut 如果在事务提交前执行,一旦事务回滚,缓存已经被删掉/更新,数据不一致。• 如果在同一个类里用 this.xxx() 调用带缓存注解的方法,不走代理,缓存直接失效;// 更新商品:先更新 DB,再删除缓存,而不是直接 @CachePut。

2401_89363342的博客 489

AIGC在游戏行业的应用:革新游戏开发与体验

AIGC(人工智能生成内容)技术正在深刻改变游戏行业,从开发到体验全面革新。在游戏开发中,AIGC可用于自动生成关卡、角色和剧情,提升开发效率;在资源制作中,通过AI生成场景、角色模型等,降低成本。

1667

C#解析基恩士(KEYENCE)PLC数据:KV协议通信与实时监控实现

KV协议是基恩士PLC使用的一种专用通信协议,通常用于与上位机进行数据交换。KV协议通过RS-232C、RS-485、Ethernet等接口与上位机通信,支持多种数据类型的读写,包括但不限于位、字、双字、浮点数等。简洁易用:KV协议的通信格式简单,易于实现。支持多种数据类型:支持位数据、字数据、定长字符串等。高效实时性:能够提供较高的实时数据交换性能,适合实时监控应用。本文介绍了如何通过C#与基恩士KV系列PLC进行通信,实现数据的解析和实时监控功能。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1810

LRU 缓存入门:它是什么、怎么用、面试怎么手写

📌 先说结论

nice_lcj520的博客 216

YOLOv11改进 | 主干/Backbone篇 | 利用RT-DETR主干网络PPHGNetV2助力yolov11有效涨点(轻量化目标检测网络)

本文给大家带来利用RT-DETR模型主干HGNet去替换YOLOv11的主干,RT-DETR是今年由百度推出的第一款实时的ViT模型,其在实时检测的领域上号称是打败了YOLO系列,其利用两个主干一个是HGNet一个是ResNet,其中HGNet就是我们今天来讲解的网络结构模型,这个网络结构目前还没有推出论文,所以其理论知识在网络上也是非常的少,我也是根据网络结构图进行了分析(精度mAP提高0.05)。YOLOv11改进系列专栏——本专栏持续复习各种顶会内容——科研必备​目录一、本文介绍。

Snu77的博客 3721

WordPress 启用区块主题后页头改了不生效或小工具全丢:先核模板部件与站点编辑器,再查 theme.json 与缓存

只改当前 URL 真正引用的模板和模板部件:首页的页头、内页的页头、结账或询盘落地页的页头可能不是同一份。先把要统一的部分抽成共享模板部件,再在各模板里引用;必须不同的,就明确做成两份部件,避免改 A 却希望 B 跟着变。颜色、字号和间距优先走theme.json和站点编辑器的全局样式:能用设计 token 解决的,不要在单个模板里堆一长段自定义 CSS。样式变体要少而稳定,运营改页时才不容易「跑偏」。改完之后清页面缓存、对象缓存和 CDN 上的 CSS,再在无痕窗口验收。

20年技术经验|专注小程序+外贸独立站|已服务500家企业,分享创业中有趣的产品和技术经验。 328

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Day103-RAG 性能优化:检索延迟/并发/批量与缓存分层

RAG 跑通不算完,扛住流量才是真本事。本文把 RAG 的端到端延迟拆成"检索—重排—生成"三段,逐段给出优化手段:Embedding 批量异步、检索并发合并、热点 Query 多级缓存、生成端流式输出,并附一张可直接照着抄的优化清单。

雨1986的博客 263

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Docker 多阶段构建反而更慢:COPY 提前一行,pip install 缓存全失效

改一行源码就触发依赖重装,构建耗时从三十秒涨到三分钟。先只拷贝依赖清单再 pip install,源码改动就不会击穿层缓存。该写法兼容所有 Docker 版本,依赖多变时需配合缓存挂载。

昨日种种,皆成今我。今日种种,皆成新我。 219

Token工厂技术拆解(11月9日)|多付218块的那个月:提示词开头写了日期,缓存一次没命中

6 万字里只留真正被问到的 2 万字,约 13,000 个 token,其余做成按需检索。每次 0.039 元,一天 330 次是 12.87 元,月 283 元。注意,283 元和第二条的 287 元差不多,可它花的人力是第二条的好几倍。这条最贵,要搭检索、要试两周,人比钱贵。别踩的三个坑:坑一,以为开关一开就有缓存。多数平台要你在内容里标出"从哪断开",不标就整段硬碰,碰不上就是零。坑二,忘了 5 分钟就过期。隔半小时再问,等于重新写一次,还是 1.25 倍。坑三,把用户的问题也塞进缓存段。

李文慧 中国开源充电桩平台第一人;李文慧 国内知名开源工作者 全栈工程师 华为云最具价值专家 38

Unity 数据存储指南:本地存储、个性化设置、缓存与 Resources/StreamingAssets 的区别

在 Unity 开发中,“数据存到哪里”、“缓存能不能清”、“打包后资源有什么区别” 是新手最容易混淆、老手也经常踩坑的问题。Unity 本地存储机制(包括 Unity 放在 C 盘的内容);Unity 个性化设置(编辑器首选项 Editor Preferences);Unity 缓存的打开、关闭与清理;打包后 Resources 与 StreamingAssets 的区别;其他可自定义存储的内容汇总。为方便理解,本文配有一个可直接运行的演示工程,所有代码见文末"配套工程说明"。

zhchyun 242

Java 项目实战: 交友项目 - 通用缓存SpringCache:配置视频列表缓存功能

在交友项目中,为视频列表接口 queryVideoList 添加 @Cacheable 实现读缓存,按用户+页码键值缓存结果;发布视频时通过 @CacheEvict(allEntries=true) 清空 videos 命名空间缓存,确保数据一致性。配合 RedisCacheConfig 设置 30 秒 TTL,形成“读缓存、写失效”的闭环。启动类启用 @EnableCaching,结合 redis-cli 验证缓存命中与失效流程,有效降低高频查询的链路开销,提升响应性能。

Wang的专栏 587

成为全栈·基础补充·缓存的层次与失效:浏览器、CDN、服务端、数据库

浏览器、CDN、服务端、数据库和客户端状态都有缓存,但它们的 key、生命周期、安全范围和失效方式并不相同。本文解释 Cache-Control 中 max-age、no-cache、no-store、private 的区别,介绍 ETag、CDN purge、服务端进程缓存和移动端 fresh/stale/expired 策略,并重点讨论会员数据隔离、写后失效以及如何用测量决定是否缓存。

FungLeo's Blog 461

【混合缓存】三种本地引擎:Caffeine / EhCache / cache2k 的抽象成本(六)

本文剖析了在统一缓存抽象层中适配Caffeine、EhCache、cache2k三类本地引擎时,因过期语义差异带来的隐性成本。核心问题在于:尽管CacheStore接口一致,但三者对“过期”的建模能力迥异——尤其cache2k无法支持读后刷新,导致TTI退化为TTL;“永不过期”需用数值模拟(如Long.MAX_VALUE/2),存在溢出风险;键级过期、热更新等行为也因引擎能力缺失而退化。最终,抽象掩盖了语义鸿沟,代价是注释、默认值与退化逻辑的复杂性,凸显了“操作统一”不等于“语义一致”的本质困境。

tantan的小记录 525
上一篇: 为什么 MyBatis 原生二级缓存“难以修复”?
下一篇: 时序数据存储数据库比对:设计货币交易平台的技术选型实践
旷野说
博客等级 码龄9年 361粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值