为什么数据库缓存如此重要?

article/2025/10/6 8:47:04

您在数据库中拥有的信息越多,它随着时间的推移就会越慢。即使是为支持许多并发请求而精心设计的数据库管理系统也将最终达到极限。

数据库缓存是处理这些性能问题的最常见策略之一。缓存涉及将数据库查询的结果保存在更快,更容易访问的位置。正确完成后,缓存将减少查询响应时间,减少数据库负载并降低成本。

但是,缓存也需要小心处理,因为它们实际上是在另一个位置创建另一个信息副本。保持数据库和缓存同步并保持最新可能比您预期的更棘手。在下一节中,我们将讨论一些最常见的数据库缓存策略。

图片标题

什么是不同的缓存策略?

手动缓存(也称为缓存搁置策略)涉及直接管理数据库和缓存。您的应用程序在启动数据库查询之前检查缓存,并在对数据库进行任何更改后更新缓存。

虽然如果正确实现有效,但手动缓存可能非常繁琐,尤其是在您需要查询多个数据库时。出于这些原因,开发人员发明了许多替代缓存策略。

直读缓存策略

在读取缓存中,应用程序首先查询缓存以查看其所需的信息是否在内部。如果没有,它将从数据库中检索信息并使用它来更新缓存。缓存提供程序或缓存库负责查询和更新缓存的详细逻辑。

当应用程序重复请求相同的数据时,读取策略最适合读取繁重的工作负载:例如,一遍又一遍地加载相同文章的新闻网站。

读取策略的一个缺点是对缓存的第一次查询将始终导致未命中,因为保证所请求的信息不在内部。为了解决这个问题,开发人员通常会使用用户可能要求的信息提前“加热”缓存。

直写缓存策略

在直写式高速缓存中,首先对高速缓存进行更新,然后对数据库进行更新。从应用程序到缓存以及从缓存到数据库都有一条直接线。与直读式缓存结合使用时,直写式策略可确保您的数据保持一致,从而无需手动缓存失效。

写缓存策略

在后写式缓存(也称为回写式高速缓存)中,应用程序首先将数据写入高速缓存。经过一段设定的延迟后,缓存也会将此信息写入数据库。后写缓存最适合写入繁重的工作负载,即使出现一些故障和停机也可以很好地执行。

基于Java的Redis缓存与Redisson

Redis是NoSQL数据库最受欢迎的选项之一,它使用键值系统来存储数据。Redisson是Java编程语言中的Redis客户端库,可以使用所有熟悉的Java集合轻松访问Redis功能。

Redisson允许您将数据放在外部存储中的地图中。您可以使用此功能实现数据库,Web服务或任何其他数据源的缓存。

Redis中的直读缓存

下面是一个Java示例,说明如何在Redis和Redisson中使用直读缓存。 

如果请求的条目在缓存中不存在,则它将由MapLoader对象加载:

MapLoader < String,String >  mapLoader  =  new  MapLoader < String,String >(){
 
    @覆盖
    public  Iterable < String >  loadAllKeys(){
        List < String >  list  =  new  ArrayList < String >();
        声明 声明 =  conn。createStatement();
        尝试 {
            ResultSet  结果 =  语句。executeQuery(“SELECT id FROM student”);
            而(结果。下一个()){
                清单。添加(结果。的getString(1));
            }
        } finally {
            声明。close();
        }
 
        返回 清单 ;
    }
 
    @覆盖
    public  String  load(String  key){
        PreparedStatement  preparedStatement  =  conn。prepareStatement(“SELECT name FROM student where id =?”);
        尝试 {
            preparedStatement。setString(1,key);
            ResultSet  result  =  preparedStatement。executeQuery();
            如果(结果。下一个()){
                返回 结果。getString(1);
            }
            return  null ;
        } finally {
            preparedStatement。close();
        }
    }
};

配置示例:

MapOptions < K,V >  options  =  MapOptions。< K,V > 默认值()
                              。loader(mapLoader);
 
RMap < K,V >  map  =  redisson。getMap(“test”,options);
// 要么
RMapCache < K,V >  map  =  redisson。getMapCache(“test”,options);
//或者提升高达45倍 
RLocalCachedMap < K,V >  map  =  redisson。getLocalCachedMap(“test”,options);
//或者提升高达45倍 
RLocalCachedMapCache < K,V >  map  =  redisson。getLocalCachedMapCache(“test”,options);

Redis中的直写缓存

下面是一个Java示例,说明如何在Redis中使用Redis中的Redis使用直写缓存。

在MapWriter对象更新缓存和数据库之前,缓存更新方法不会返回:

MapWriter < String,String >  mapWriter  =  new  MapWriter < String,String >(){
 
    @覆盖
    public  void  write(Map < String,String >  map){
        PreparedStatement  preparedStatement  =  conn。prepareStatement(“INSERT INTO student(id,name)values(?,?)”);
        尝试 {
            对于(条目< 字符串,字符串>  条目:地图。的entrySet()){
                preparedStatement。的SetString(1,条目。信息getKey());
                preparedStatement。的SetString(2,条目。的getValue());
                preparedStatement。addBatch();
            }
            preparedStatement。executeBatch();
        } finally {
            preparedStatement。close();
        }
    }
 
    @覆盖
    public  void  delete(Collection < String >  keys){
        PreparedStatement  preparedStatement  =  conn。prepareStatement(“DELETE FROM student where id =?”);
        尝试 {
            for(String  key:keys){
                preparedStatement。setString(1,key);
                preparedStatement。addBatch();
            }
            preparedStatement。executeBatch();
        } finally {
            preparedStatement。close();
        }
    }
};

配置示例:

MapOptions < K,V >  options  =  MapOptions。< K,V > 默认值()
                              。writer(mapWriter)
                              。writeMode(WriteMode。WRITE_THROUGH);
 
RMap < K,V >  map  =  redisson。getMap(“test”,options);
// 要么
RMapCache < K,V >  map  =  redisson。getMapCache(“test”,options);
//或者提升高达45倍 
RLocalCachedMap < K,V >  map  =  redisson。getLocalCachedMap(“test”,options);
//或者提升高达45倍 
RLocalCachedMapCache < K,V >  map  =  redisson。getLocalCachedMapCache(“test”,options);

Redis中的写缓存

MapWriter接口还用于异步提交对Map对象(缓存)和外部存储(数据库)的更新。所有映射更新都按批次累积,并以定义的延迟异步写入。

writeBehindDelay - 批量写入或删除操作的延迟。默认值为1000毫秒。

writeBehindBatchSize  - 批量大小。每个批处理包含Map Entry写入或删除命令。默认值为50。

下面,我们看到Redisson中基于Redis的后写缓存实现的配置的Java示例:

MapOptions < K,V >  options  =  MapOptions。< K,V > 默认值()
                              。writer(mapWriter)
                              。writeMode(WriteMode。WRITE_BEHIND)
                              。writeBehindDelay(5000)
                              。writeBehindBatchSize(100);
 
RMap < K,V >  map  =  redisson。getMap(“test”,options);
// 要么
RMapCache < K,V >  map  =  redisson。getMapCache(“test”,options);
//或者提升高达45倍 
RLocalCachedMap < K,V >  map  =  redisson。getLocalCachedMap(“test”,options);
//或者提升高达45倍 
RLocalCachedMapCache < K,V >  map  =  redisson。getLocalCachedMapCache(“test”,options);

所有讨论的策略可用于在旋转地图,RMapCache,RLocalCachedMap和RLocalCachedMapCache对象Redisson。使用后两个对象可以使Redis中的读取操作速度提高45倍。


http://chatgpt.dhexx.cn/article/pX7kVvwJ.shtml

相关文章

缓存 (模拟两种:数据库提供数据到缓存、外界提供数据到缓存)

一、缓存的作用 因此就有了缓存的作用&#xff1a; 代码模拟上面缓存的作用如下所示&#xff1a; 就拿以前我们做的通过id查询单条数据功能&#xff1a; 当开启服务器后&#xff0c;客户端访问该通过id查询单条数据功能时&#xff08;假设连续访问两次&#xff09;&#xff1a…

mysql的查询缓存

提高单台节点的性能无外乎就那么几种方式&#xff0c;缓存是首当其冲的&#xff0c;因为内存的性能比磁盘高的太多。缓存也是一种典型的空间换时间的策略 缓存的实现也有太多的方式&#xff0c;从静态页面缓存到服务端动态缓存&#xff0c;再到数据库级别缓存等等。随着大数据的…

缓存(本地缓存、分布式缓存)与数据库之间的数据一致性问题?

在现在的系统架构中&#xff0c;缓存的地位可以说是非常高的。因为在互联网的时代&#xff0c;请求的并发量可能会非常高&#xff0c;但是关系型数据库对于高并发的处理能力并不是非常强&#xff0c;而缓存由于是在内存中处理&#xff0c;并不需要磁盘的IO&#xff0c;所以非常…

mysql数据库缓存

一、开启缓存 mysql 开启查询缓存可以有两种方法来开启一种是使用set命令来进行开启&#xff0c;另一种是直接修改my.ini文件来直接设置都是非常的简单的哦。 开启缓存&#xff0c;设置缓存大小&#xff0c;具体实施如下&#xff1a; 1、修改配置文件my.ini windows下是my.i…

mysql 缓存机制

mysql缓存机制就是缓存sql 文本及缓存结果&#xff0c;用KV形式保存再服务器内存中&#xff0c;如果运行相同的sql,服务器直接从缓存中去获取结果&#xff0c;不需要在再去解析、优化、执行sql。 如果这个表修改了&#xff0c;那么使用这个表中的所有缓存将不再有效&#xff0c…

数据库缓存层

一 常见的缓存形式 : 1.文件缓存 (为了避免I/O开销,尽量使用内存缓存) 2.内存缓存 二 为什么要使用缓存 缓存数据是为了让客户端很少甚至不访问数据库服务器进行的数据查询,高并发下,能最大程度降低对数据库服务器的访问压力 一般的数据请求: 用户请求->数据查询->…

SQL查询缓存

适合读者 本教程适合于那些对缓存SQL查询以减少数据库连接与执行的负载、提高脚本性能感兴趣的PHP程序员。 概述 许多站点使用数据库作为站点数据存储的容器。数据库包含了产器信息、目录结构、文章或者留言本&#xff0c;有些数据很可能是完全静态的&#xff0c;这些将会从一个…

数据库之查询缓存

查询缓存配置 查看当前的MySQL数据库是否支持查询缓存SHOW VARIABLES LIKE have_query_cache; 查看当前MySQL是否开启了查询缓存SHOW VARIABLES LIKE query_cache_type; 查看查询缓存的占用大小SHOW VARIABLES LIKE query_cache_size; 查看查询缓存的状态信息show status li…

数据库缓存

一、什么是数据库缓存 我们知道常见的数据库&#xff0c;比如oracle、mysql等&#xff0c;数据都是存放在磁盘中。虽然在数据库层也做了对应的缓存&#xff0c;但这种数据库层次的缓存一般针对的是查询内容&#xff0c;而且粒度也太小&#xff0c;一般只有表中数据没有变更的时…

【技术干货】缓存随谈系列之一:数据库缓存

本文作者: 乔锐杰 现担任上海驻云信息科技有限公司运维总监/架构师。曾任职过黑客讲师、java软件工程师/网站架构师、高级运维、阿里云架构师等职位。维护过上千台服务器,主导过众安保险、新华社等千万级上云架构。在云端运维、分布式集群架构等方面有着丰富的经验。 以…

内连接、外连接、全连接图示语法

外连接 外连接分为外左连接(left outer join)和外右连接(right outer join) left outer join 与 left join 等价&#xff0c; 一般写成left join right outer join 与 right join等价&#xff0c; 一般写成right join左连接&#xff1a;左侧交集部分 语法&#xff1a;…

MySQL 内连接、外连接、左连接、右连接、全连接

建表语句&#xff1a; CREATE TABLE a_table (a_id int(11) DEFAULT NULL,a_name varchar(10) DEFAULT NULL,a_part varchar(10) DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8CREATE TABLE b_table (b_id int(11) DEFAULT NULL,b_name varchar(10) DEFAULT NULL,b_part v…

SQL中的各种连接的区别总结(内连接,左连接,左外连接,右连接,右外连接,全连接,全外连接)

在数据库中建立两张表方便大家理解&#xff0c;teacher和student表(student表中的teacherid字段是对应teacher表中的ID&#xff0c;举个例子张三的老师就是李四&#xff0c;没有teacherid就是这个人暂时没有老师) INNER JOIN: 返回两个表的匹配得上的数据&#xff0c;不匹配不…

MYSQL语法:左连接、右连接、内连接、全外连接

文章目录 概念上手使用left join(左连接)rint join(右连接)inner join&#xff08;内连接&#xff0c;等同join&#xff09;full join&#xff08;全连接&#xff0c;等同full outer join&#xff09; 概念 left join&#xff08;左连接&#xff09;&#xff1a;返回包括左表中…

MySQL 的等值连接、交叉连接、左外连接 、右外连接、全外连接实例

1. 测试数据 测试数据如下所示&#xff0c;数据库脚本&#xff08;含数据&#xff09;在文章最后的附录中给出。 测试工具&#xff1a;MySQL8.0 &#xff0c; Navicat Premium。 首先是一个班级表&#xff1a;class&#xff0c;class表中的数据如下所示。 学生表: student&a…

数据库学习之MySQL (十六)—— SQL99 外连接 左外连接 右外连接 全外连接 交叉连接

文章目录 外连接 之 左外连接 与 右外连接为啥要用外连接全外连接总结 内连接 外连接交叉连接 外连接 之 左外连接 与 右外连接 我们先来看个之前的 女神男朋友的案例 传送&#xff1a;数据库学习之MySQL (十三&#xff09;——多表查询 SQL92 SQL99 连接种类划分 我们先考虑…

ORACLE的左右连接,全外连接

先上概念 oracle连接分为&#xff1a; 左外连接&#xff1a;左表不加限制&#xff0c;保留左表的数据&#xff0c;匹配右表&#xff0c;右表没有匹配到的行中的列显示为null。 右外连接&#xff1a;右表不加限制&#xff0c;保留右表的数据。匹配左表&#xff0c;左表没有匹配…

SQL的内连接、左连接、右连接、 交叉连接、全外连接

sql表连接分成 外连接 、 内连接 和 交叉连接。. 外连接包括三种,分别是左外连接、右外连接、全外连接。. 对应的sql关键字:LEFT/RIGHT/FULL OUTER JOIN,通常我们都省略OUTER关键字,写成LEFT/RIGHT/FULL JOIN。. 在左、右外连接中都会以一种表为基表&#xff0c;基表的所有行、…

Mysql中实现全外连接

MySql中多表查询只提供了内连接&#xff0c;左外连接与右外连接&#xff1a; table_reference {[INNER] JOIN | {LEFT|RIGHT} [OUTER] JOIN} table_reference ON conditional_expr 1】INNER JOIN ON内连接&#xff08;只写join时默认为内连接&#xff09; SELECT * FROM emp e…

mysql 全外连接报错的原因

mysql 不支持 直接写full outer join 或者 full join来表示全外连接但是可以用left right union right 代替。 全外连接图&#xff08;非原创图&#xff09; 下面的是全外连接例子&#xff1a; select * from table a A&#xff08;A为别名&#xff09;LEFT JOIN table b B …