使用Redis和Java进行数据库缓存

使用Redis和Java探索数据库缓存,并查看一些不同的缓存策略。最近在优锐课学习收获颇多,记录下来大家一起进步!

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

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

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

但是,缓存也需要谨慎处理,因为它们实际上是在单独的位置中复制了你的另一份信息。保持数据库和缓存同步并保持最新状态可能是比你预期的棘手的挑战。在下一节中,我们将讨论一些最常见的数据库缓存策略。

有哪些不同的缓存策略?

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

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

Read-Through缓存策略

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

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

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

Write-Through 缓存策略

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

Write-Behind缓存策略

在Write-Behind缓存(也称为Write-Back缓存)中,应用程序首先将数据写入高速缓存。 经过一段时间的延迟后,高速缓存还将这些信息写入数据库。Write-Behind缓存最适合于繁重的写工作负载,即使出现一些故障和停机也可以表现良好。

使用Redisson的基于Java的Redis缓存

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

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

Redis中的Read-Through缓存

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

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

MapLoader<String, String> mapLoader = new MapLoader<String, String>() {

    @Override

    public Iterable<String> loadAllKeys() {

        List<String> list = new ArrayList<String>();

        Statement statement = conn.createStatement();

        try {

            ResultSet result = statement.executeQuery("SELECT id FROM student");

            while (result.next()) {

                list.add(result.getString(1));

            }

        } finally {

            statement.close();

        }

        return list;

    }

    @Override

    public String load(String key) {

        PreparedStatement preparedStatement = conn.prepareStatement("SELECT name FROM student where id = ?");

        try {

            preparedStatement.setString(1, key);

            ResultSet result = preparedStatement.executeQuery();

            if (result.next()) {

                return result.getString(1);

            }

            return null;

        } finally {

            preparedStatement.close();

        }

    }

};

Configuration example:

MapOptions<K, V> options = MapOptions.<K, V>defaults()

                              .loader(mapLoader);

RMap<K, V> map = redisson.getMap("test", options);

// or

RMapCache<K, V> map = redisson.getMapCache("test", options);

// or with boost up to 45x times 

RLocalCachedMap<K, V> map = redisson.getLocalCachedMap("test", options);

// or with boost up to 45x times 

RLocalCachedMapCache<K, V> map = redisson.getLocalCachedMapCache("test", options);

Redis 中的Write-Through缓存

下面是一个Java示例,说明如何在Redis和Redisson中的Redis中使用Write-Through缓存。

直到MapWriter对象更新了缓存和数据库后,缓存更新方法才会返回:

MapWriter<String, String> mapWriter = new MapWriter<String, String>() {

    @Override

    public void write(Map<String, String> map) {

        PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO student (id, name) values (?, ?)");

        try {

            for (Entry<String, String> entry : map.entrySet()) {

                preparedStatement.setString(1, entry.getKey());

                preparedStatement.setString(2, entry.getValue());

                preparedStatement.addBatch();

            }

            preparedStatement.executeBatch();

        } finally {

            preparedStatement.close();

        }

    }

    @Override

    public void delete(Collection<String> keys) {

        PreparedStatement preparedStatement = conn.prepareStatement("DELETE FROM student where id = ?");

        try {

            for (String key : keys) {

                preparedStatement.setString(1, key);

                preparedStatement.addBatch();

            }

            preparedStatement.executeBatch();

        } finally {

            preparedStatement.close();

        }

    }

};

Configuration example:

MapOptions<K, V> options = MapOptions.<K, V>defaults()

                              .writer(mapWriter)

                              .writeMode(WriteMode.WRITE_THROUGH);

RMap<K, V> map = redisson.getMap("test", options);

// or

RMapCache<K, V> map = redisson.getMapCache("test", options);

// or with boost up to 45x times 

RLocalCachedMap<K, V> map = redisson.getLocalCachedMap("test", options);

// or with boost up to 45x times 

RLocalCachedMapCache<K, V> map = redisson.getLocalCachedMapCache("test", options);

Redis 中的Write-Behind缓存

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

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

writeBehindBatchSize —批处理的大小。每批包含“映射条目”写入或删除命令。默认值为50。

下面,我们看到一个Redisson中基于Redis的Write-Behind缓存实现的Java配置示例:

MapOptions<K, V> options = MapOptions.<K, V>defaults()

                              .writer(mapWriter)

                              .writeMode(WriteMode.WRITE_BEHIND)

                              .writeBehindDelay(5000)

                              .writeBehindBatchSize(100);

RMap<K, V> map = redisson.getMap("test", options);

// or

RMapCache<K, V> map = redisson.getMapCache("test", options);

// or with boost up to 45x times 

RLocalCachedMap<K, V> map = redisson.getLocalCachedMap("test", options);

// or with boost up to 45x times 

RLocalCachedMapCache<K, V> map = redisson.getLocalCachedMapCache("test", options);

所有讨论的策略都可用于Redisson中的RMap,RMapCache,RLocalCachedMap和RLocalCachedMapCache对象。使用后两个对象可以使Redis中的读取操作快45倍。

感谢阅读!

原文地址:https://www.cnblogs.com/zhao06666guo77/p/12273738.html

时间: 2024-10-10 01:48:52

使用Redis和Java进行数据库缓存的相关文章

java模拟数据库缓存

实现缓存一些数据到本地,避免重复查询数据库,对数据库造成压力,代码如下: package threadLock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class CatheDemo { private Map<S

Java环境配置 数据库 缓存Redis Nosql MongoDB 安装

系统选择 centos 7.0 1.java安装篇 rpm -qa |grep java 检测是否java yum remove java-1.7.0-openjdk 使用命令删除java 到oracle官方下载java安装包 rpm -ivh jdk-7u60-linux-x64.rpm ->安装jdk 2.Tomcat 安装篇 在apache官方下载tomcat wget http://apache.fayea.com/apache-mirror/tomcat/tomcat-7/v7.0.5

构建高性能数据库缓存之redis主从复制

一.什么是redis主从复制? 主从复制,当用户往Master端写入数据时,通过Redis Sync机制将数据文件发送至Slave,Slave也会执行相同的操作确保数据一致:且实现Redis的主从复制非常简单. 二.redis主从复制特点 1.同一个Master可以拥有多个Slaves. 2.Master下的Slave还可以接受同一架构中其它slave的链接与同步请求,实现数据的级联复制,即Master->Slave->Slave模式: 3.Master以非阻塞的方式同步数据至slave,这将

用Redis作Mysql数据库缓存

使用redis作mysql数据库缓存时,需要考虑两个问题: 1.确定用何种数据结构存储来自Mysql的数据; 2.在确定数据结构之后,用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是按表存储的;更微观地看,这些表都是按行存储的.每执行一次select查询,Mysql都会返回一个结果集,这个结果集由若干行组成.所以,一个自然而然的想法就是在Redis中找到一种对应于Mysql行的数据结构.Redis中提供了五种基本数据结构,即字符串(string).列表(list).哈希(hash

Redis简介以及和其他缓存数据库的区别

一.Redis简介 Redis 是一个开源的内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如字符串(Strings),散列(Hashes),列表(Lists),集合(Sets),有序集合(Sorted Sets或者是ZSet) 与范围查询, Bitmaps,Hyperloglogs 和 地理空间(Geospatial)索引半径查询. 其中常见的数据结构类型有String.List.Set.Hash.ZSet这5种. Redis 内置了复制(Replic

Redis整合Spring结合使用缓存实例

摘要:本文介绍了如何在Spring中配置redis,并通过Spring中AOP的思想,将缓存的方法切入到有需要进入缓存的类或方法前面. 一.Redis介绍 什么是Redis? redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set –有序集合)和hash(哈希类型).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作

Redis与Java - 数据结构

Redis与Java 标签 : Java与NoSQL Redis(REmote DIctionary Server) is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets wit

使用Redis做MyBatis的二级缓存

1. 介绍 使用mybatis时可以使用二级缓存提高查询速度,进而改善用户体验. 使用redis做mybatis的二级缓存可是内存可控<如将单独的服务器部署出来用于二级缓存>,管理方便. 2. 使用思路 2.1 配置redis.xml 设置redis服务连接各参数 2.1 在配置文件中使用 <setting> 标签,设置开启二级缓存: 2.2 在mapper.xml 中使用<cache type="com.demo.RedisCacheClass" /&g

Redis整合Spring结合使用缓存实例(转)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文介绍了如何在Spring中配置redis,并通过Spring中AOP的思想,将缓存的方法切入到有需要进入缓存的类或方法前面. 一.Redis介绍 什么是Redis? redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和h