【MyBatis源码】CacheKey缓存键的原理分析
文章目录
- Mybatis缓存设计
- 缓存KEY的设计
- CacheKey类主体
- CacheKey组成
- CacheKey如何保证缓存key的唯一性
Mybatis缓存设计
MyBatis 每秒过滤众多数据库查询操作,这对 MyBatis 缓存键的设计提出了很高的要求。MyBatis缓存键要满足以下几点。
无碰撞:必须保证两条不同的查询请求生成的键不一致,这是最重要也是必须满足的要求。否则会引发查询操作命中错误的缓存,并返回错误的结果。
高效比较:每次缓存查询操作都可能会引发键之间的多次比较,因此该操作必须是高效的。
高效生成:每次缓存查询和写入操作前都需要生成缓存的键,因此该操作也必须是高效的。
在编程中,我们常使用数值、字符串等简单类型作为键,然而,这类键容易产生碰撞。为了防止碰撞的发生,需要将键的生成机制设计得非常复杂,这又降低了键的比较效率和生成效率。因此,准确度和效率之间往往是相互制约的。
为了解决以上问题,MyBatis设计了一个 CacheKey类作为缓存键。整个 CacheKey设计得并不复杂,但又非常精巧。

设计图解释:
【1】 Mybatis缓存的使用和我们一般使用缓存方式相同,使用一个内存缓存(map)作为本地容器。对于查询请求优先查询本地缓存,如果有直接返回,没有查询数据库,并将数据库查询结果写入到缓存中。
【2】 Mybatis使用CacheKey类作为缓存(map)的key,重写了其hashcode和equal方法。
【3】 CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); Mybatis主要根据mapper信息,参数值,分页信息,SQL信息设计缓存key
缓存KEY的设计
CacheKey类主体
public class CacheKey implements Cloneable, Serializable {/*** 乘数,用来计算hashcode时使用*/private final int multiplier;/*** 哈希值,整个CacheKey的哈希值*/private int hashcode;/*** 求和校验码*/private long checksum;/*** 更新次数,整个CacheKey的更新次数*/private int count;/*** 更新历史*/private List<Object> updateList;public void update(Object object) {int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);count++;checksum += baseHashCode;baseHashCode *= count;hashcode = multiplier * hashcode + baseHashCode;updateList.add(object);}public void updateAll(Object[] objects) {for (Object o : objects) {update(o);}}@Overridepublic boolean equals(Object object) {if (this == object) {return true;}if (!(object instanceof CacheKey)) {return false;}final CacheKey cacheKey = (CacheKey) object;if (hashcode != cacheKey.hashcode) {return false;}if (checksum != cacheKey.checksum) {return false;}if (count != cacheKey.count) {return false;}for (int i = 0; i < updateList.size(); i++) {Object thisObject = updateList.get(i);Object thatObject = cacheKey.updateList.get(i);if (!ArrayUtil.equals(thisObject, thatObject)) {return false;}}return true;}@Overridepublic int hashCode() {return hashcode;}
}
CacheKey组成
org.apache.ibatis.executor.BaseExecutor#createCacheKey
// 创建CacheKey对象CacheKey cacheKey = new CacheKey();// mapper-idcacheKey.update(ms.getId());// 分页参数cacheKey.update(rowBounds.getOffset());cacheKey.update(rowBounds.getLimit());// 执行的SQL(带有占位符的)cacheKey.update(boundSql.getSql());// 执行SQL参数value值cacheKey.update(value);// 环境配置idcacheKey.update(configuration.getEnvironment().getId());
CacheKey主要由5部分组成:
【1】 mapper接口对应的statementId
【2】 分页参数
【3】 执行SQL
【4】 传入参数的值
【5】 当前环境的ID
CacheKey如何保证缓存key的唯一性
CacheKey首先类设计了多个重要属性,这些属性为结合传入的参数信息进行组合计算以提高缓存key的唯一性,并能够以较高的性能进行比较计算。

其中hashcode的计算主要通过update方法进行计算
public void update(Object object) {int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);count++;checksum += baseHashCode;baseHashCode *= count;hashcode = multiplier * hashcode + baseHashCode;updateList.add(object);}
在比较 CacheKey对象是否相等时,会先进行类型判断,然后进行 hashcode、checksum、count的比较,只要有一项不相同则表明两个对象不同。以上操作都比较简单,能在很短的时间内完成。如果上面的各项属性完全一致,则会详细比较两个CacheKey 对象的变动历史 updateList,这一步操作相对复杂,但是能保证绝对不会出现碰撞问题。


【CacheKey生成的结果示例】
2042432675:5771996351:user.selectById:0:2147483647:select * from t_user where id = ? and name = ?:1:null:development
MyBatis 还准备了一个 NullCacheKey,该类用来充当一个空键使用。在缓存查询中,如果发现某个 CacheKey信息不全,则会返回 NullCacheKey对象,类似于返回一个null值。但是 NullCacheKey毕竟是 CacheKey的子类,在接下来的处理中不会引发空指针异常。这种设计方式也非常值得我们借鉴。
MyBatis生成的 CacheKey 对象中包含了这次查询的所有信息,包括查询语句的 id、查询的翻页限制、数据总量、完整的 SQL语句,这些信息一致就保证了两次查询的一致。结合 CacheKey的 equals方法,我们知道只要通过 equals方法判断两个CacheKey对象相等,则两次查询操作的条件必定是完全一致的。
相关文章:
【MyBatis源码】CacheKey缓存键的原理分析
文章目录 Mybatis缓存设计缓存KEY的设计CacheKey类主体CacheKey组成CacheKey如何保证缓存key的唯一性 Mybatis缓存设计 MyBatis 每秒过滤众多数据库查询操作,这对 MyBatis 缓存键的设计提出了很高的要求。MyBatis缓存键要满足以下几点。 无碰撞:必须保证…...
034_Structural_Transient_In_Matlab结构动力学问题求解
结构动态问题 问题描述 我们试着给前面已经做过的问题上加一点有趣的东西。 结构静力学求解 当时求解这个问题,在最外面的竖直切面加载了一个静态的固定的力。下面我们试试看在上方的表面增加一个脉冲压力载荷。 采用统一的有限元框架,定义问题&…...
项目模块十五:HttpResponse模块
一、模块设计思路 存储HTTP应答要素,提供简单接口 二、成员变量 int _status; // 应答状态码 unordered_map<string, string> _headers; // 报头字段 string _body; // 应答正文 bool _redirect_flag; // 是否重定向信息 stri…...
推荐一款优秀的pdf编辑器:Ashampoo PDF Pro
Ashampoo PDF Pro是管理和编辑 PDF 文档的完整解决方案。程序拥有您创建、转换、编辑和保护文档所需的一切功能。根据需要可以创建特定大小的文档,跨设备可读,还可以保护文件。现在您还能像编辑Word文档一样编辑PDF! 软件特点 轻松处理文字 如 Microso…...
【系统架构设计师】2024年上半年真题论文: 论模型驱动架构设计方法及其应用(包括解题思路和素材)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2024年上半年 试题3)解题思路1、模型驱动架构能够为软件开发带来的好处2、模型驱动架构的开发过程论文素材参考真题题目(2024年上半年 试题3) 模型驱动架构设计是一种用于应用系统开发的软件设计方法…...
国内短剧源码短剧系统搭建小程序部署H5、APP打造短剧平台
在当今的互联网时代,短剧作为一种新兴的娱乐形式,受到了越来越多用户的喜爱。为了提供更好的用户体验和满足用户需求,一个好的短剧系统需要具备多元化的功能和优质的界面设计。 本文将介绍国内短剧源码短剧系统搭建小程序部署H5、APP所需的…...
Java集合框架面试指南
Java集合框架面试指南 文章目录 Java集合框架面试指南ArrayList特点:LinkedList特点:ArrayDeque特点:PriorityQueue特点:HashMap特点:HashSet特点:LinkedHashMap特点LinkedHashMap经典用法 TreeMap特点Conc…...
八、MapReduce 大规模数据处理深度剖析与实战指南
MapReduce 大规模数据处理深度剖析与实战指南 一、绪论 在当今的大数据时代背景下,海量数据的处理已然成为企业及科研机构所面临的重大挑战。MapReduce 作为一种高效的分布式计算模型,在大规模数据处理领域中发挥着至关重要的作用。本文将深入阐释 MapR…...
开源免费的API网关介绍与选型
api网关的主要作用 API网关在现代微服务架构中扮演着至关重要的角色,它作为内外部系统通信的桥梁,不仅简化了服务调用过程,还增强了系统的安全性与可管理性。例如,当企业希望将内部的服务开放给外部合作伙伴使用时,直…...
OpenCV视觉分析之目标跟踪(5)目标跟踪类TrackerMIL的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 MIL 算法以在线方式训练分类器,以将目标从背景中分离出来。多重实例学习(Multiple Instance Learning)通过在…...
二级列表联动
介绍 本示例主要介绍了List组件实现二级联动(Cascading List)的场景。 该场景多用于商品种类的选择、照片不同类型选择等场景。 效果图 使用说明: 滑动二级列表侧控件(点击没用),一级列表随之滚动。&…...
「C/C++」C++ 标准库 之 #include<sstream> 字符串流库
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
深入理解跨域资源共享(CORS)安全问题原理及解决思路
目录 引言 CORS 基础 CORS 安全问题原理 解决思路 结论 引言 跨域资源共享(CORS, Cross-Origin Resource Sharing)是现代Web应用中不可或缺的一部分,特别是在前后端分离的架构中。CORS允许一个域上的Web应用请求另一个域上的资源&#…...
【汽车租聘管理与推荐】Python+Django网页界面+推荐算法+管理系统网站
一、介绍 汽车租聘管理与推荐系统。本系统使用Python作为主要编程语言,前端采用HTML、CSS、BootStrap等技术搭建前端界面,后端采用Django框架处理用户的请求。创新点:使用协同过滤推荐算法实现对当前用户个性化推荐。 其主要功能如下&#…...
Linux常见指令大全(必要+知识点)
目录 ls 指令☑️ 在Windows中会自动显示当前目录当中的所有子目录与文件,但是在Linux中要用到ls指令。 语法: ls [选项][目录或文件] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以…...
iOS用rime且导入自制输入方案
iPhone 16 的 cantonese 只能打传统汉字,没有繁简转换,m d sh d。考虑用「仓」输入法 [1] 使用 Rime 打字,且希望导入自制方案 [2]。 仓输入法有几种导入方案的方法,见 [3],此处记录 wifi 上传法。准备工作࿱…...
Linux 进程终止 进程等待
目录 进程终止 退出码 错误码 代码异常终止(信号详解) exit _exit 进程等待 概念 等待的原因 wait 函数原型 参数 返回值 监控脚本 waitpid 概念 函数原型 参数 返回值 WIFEXITED(status) WEXITSTATUS(status) 问题 为什么不用全局变量获得子进程的退出信…...
VBA 64位API声明语句第003讲
跟我学VBA,我这里专注VBA, 授人以渔。我98年开始,从源码接触VBA已经20余年了,随着年龄的增长,越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友,都来学习VBA,利用VBA,起码可以提高…...
【问题记录】解决VMware虚拟机中鼠标侧键无法使用的问题
前言 有项目需要在Linux系统中开发,因为要测试Linux中相关功能,要用到shell,在Windows中开发太麻烦了,因此我选择使用UbuntuXfce4桌面来开发,这里我用到了Linux版本的IDEA,除了快捷键经常和系统快捷键冲突…...
Naive UI 级联选择器 Cascader的:render-lable怎么使用(Vue3 + TS)(鼠标悬停该条数据的时候展示全部内容)
项目场景: 在渲染Cascader级联选择器后,当文字过长的时候,多出来的部分会显示成省略号,这使我们不能很清晰的看到该条数据的完整信息,就需要加一个鼠标悬停展示完整内容。 解决方案: vue: &l…...
StructBERT在嵌入式Linux设备上的轻量化部署方案
StructBERT在嵌入式Linux设备上的轻量化部署方案 1. 为什么要在树莓派上跑StructBERT 你可能已经试过在笔记本或服务器上运行大模型,但有没有想过让AI在树莓派这样的小设备上工作?不是为了炫技,而是因为很多实际场景根本用不上那么大的机器…...
NCCL中RoCE与RDMA的深度解析:如何优化分布式训练网络性能
1. 为什么RoCE和RDMA对分布式训练如此重要? 第一次接触分布式训练时,我盯着日志里不断跳动的通信耗时直发愁。8块GPU明明都在满负荷运转,但总训练时间就是比单卡8要长不少。后来用NVIDIA的Nsight工具一分析,发现超过30%的时间都花…...
电视盒子变身高性能服务器:Armbian系统终极刷机指南
电视盒子变身高性能服务器:Armbian系统终极刷机指南 【免费下载链接】amlogic-s9xxx-armbian Supports running Armbian on Amlogic, Allwinner, and Rockchip devices. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s905l, rk3588, rk…...
Qwen2.5-VL-7B-Instruct开源大模型:支持中文优先的多模态理解部署方案
Qwen2.5-VL-7B-Instruct开源大模型:支持中文优先的多模态理解部署方案 1. 项目概述 Qwen2.5-VL-7B-Instruct是一款开源的视觉-语言多模态大模型,特别针对中文场景进行了优化。该模型能够同时处理图像和文本输入,实现跨模态的理解与生成任务…...
MiniCPM-o-4.5-nvidia-FlagOS部署运维:使用Docker Compose管理多服务依赖
MiniCPM-o-4.5-nvidia-FlagOS部署运维:使用Docker Compose管理多服务依赖 你是不是也遇到过这种情况?想部署一个AI模型,发现它依赖一堆东西:模型服务本身、数据库、缓存、可能还有别的辅助工具。一个个手动去装、去配置、去启动&…...
Shiny框架终极指南:输入控件与输出渲染的完美交互原理
Shiny框架终极指南:输入控件与输出渲染的完美交互原理 【免费下载链接】shiny Easy interactive web applications with R 项目地址: https://gitcode.com/gh_mirrors/sh/shiny Shiny是R语言生态中一款强大的交互式Web应用框架,它让数据科学家和分…...
告别Swagger注解污染:用smart-doc + Maven插件5分钟生成整洁API文档(SpringBoot实战)
零侵入API文档革命:smart-doc在SpringBoot项目中的极致实践 如果你曾经被Swagger注解污染代码所困扰,或是厌倦了在业务逻辑中嵌入大量文档相关注解,那么smart-doc可能会成为你API文档管理的新选择。作为一款基于源码解析的文档生成工具&#…...
noice.nvim终极性能优化指南:让你的Neovim编辑器运行如飞
noice.nvim终极性能优化指南:让你的Neovim编辑器运行如飞 【免费下载链接】noice.nvim 💥 Highly experimental plugin that completely replaces the UI for messages, cmdline and the popupmenu. 项目地址: https://gitcode.com/gh_mirrors/no/noic…...
Godot-MCP:如何通过双向语义桥梁解决游戏开发中的创意断层问题
Godot-MCP:如何通过双向语义桥梁解决游戏开发中的创意断层问题 【免费下载链接】Godot-MCP An MCP for Godot that lets you create and edit games in the Godot game engine with tools like Claude 项目地址: https://gitcode.com/gh_mirrors/god/Godot-MCP …...
【ROS2 基础】ROS2与Colcon核心指令速查手册与避坑指南
为了在 ROS2 的日常开发中提升效率,本文为您整理了一份结构化的核心指令速查清单。去除了冗长的理论,直击实战痛点,并附带了多平台差异、性能优化数据以及常见报错的修复方案。 文章目录[TOC]一、 快速入门:3步跑通基础流程二、 版…...
