SpringCache学习之操作redis

小编 2026-06-04 阅读:1959 评论:0
一、redis快速入门  1、redis简介  在java领域,常见的四大缓存分别是ehcach...

一、redis快速入门

  1、redis简介

  在java领域,常见的四大缓存分别是ehcache,memcached,redis,guava-cache,其中redis与其他类型缓存相比,有着得天独厚的优势:

  1. 它是基于内存的数据库,什么意思呢?由于受磁盘IO影响,它所有操作都在内存当中,用以提高性能,同时采用异步的方式将数据保存在硬盘当中。
  2. 与memcached相比,redis支持多种数据类型,string,list,set,sorted set,hash。让我们使用起来更加灵活
  3. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行  
  4. 丰富的特性:可用于缓存,消息,可以设置key的过期时间,过期后将会自动删除对应的记录 
  5. redis是单线程单进程的,它利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。

 

 2、redis常见的数据类型

   2.1   redis的key:

     我们可以使用任何二进制序列当我们的键,过长过短的键都不建议使用,在这里建议大家使用尝试使用一个模式。例如,“object-type:id”是一个比较推荐的方式,举个例子,我们可以这样来定义键:“user:1000”。点或破折号通常用于多字字段。

    2.2  strings: 该类型是最基本的数据类型,也是最常见的数据类型。我们可以使用set 或get 来设置和获取对应的值:

> set mykey somevalueOK> get mykey"somevalue"

    在这里面set 如果已经存在的key 会替换已有的值。注意value的值不要大于512M

    另外,我们可以使用mset 与 mget来设置和获取多个值,如下:

> mset a 10 b 20 c 30OK> mget a b c1) "10"2) "20"3) "30"

    我们可以使用exists判断key对应的值是否存在,del则是删除key对应的值

> set mykey helloOK> exists mykey(integer) 1> del mykey(integer) 1> exists mykey(integer) 0

     我们也可以指定key值对应的过期时间:(单位为秒)

> set key some-valueOK> expire key 5(integer) 1> get key (immediately)"some-value"> get key (after some time)(nil)

 

  2.3 lists类型:这个类似于我们的集合类型,可以存放多个值,我们可以使用lpush(在头部添加)与rpush(在尾部添加)来添加对应的元素:

  

 rpush mylist A(integer) 1> rpush mylist B(integer) 2> lpush mylist first(integer) 3> lrange mylist 0 -11) "first"2) "A"3) "B"

  其中lrange 是取一定范围的元素

 

  2.4 Hashes 这个类似于key->key ,value的形式,我们可以使用hmset与hget来取值

> hmset user:1000 username antirez birthyear 1977 verified 1OK> hget user:1000 username"antirez"> hget user:1000 birthyear"1977"> hgetall user:10001) "username"2) "antirez"3) "birthyear"4) "1977"5) "verified"6) "1"

 

  2.5、SETS:存放了一系列无序的字符串集合,我们可以通过sadd与smembers来取值:

> sadd myset 1 2 3(integer) 3> smembers myset1. 32. 13. 2

 

  3、redis中的事务

    MULTI 命令用于开启一个事务,它总是返回 OK 。 MULTI执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。redis中事务不存在回滚,我们这么操作试试:

localhost:0>multi"OK"localhost:0>set test abc"QUEUED"localhost:0>incr test"QUEUED"localhost:0>exec 1)  "OK" 2)  "ERR value is not an integer or out of range"localhost:0>get test"abc"

如果事务当中入队不成功,我们可以看一下例子:

localhost:0>multi"OK"localhost:0>set test abcd"QUEUED"localhost:0>test abc"ERR unknown command 'test'"localhost:0>exec"EXECABORT Transaction discarded because of previous errors."localhost:0>get test"abc"

此时就会终止我们提交事务

另外我们调用 DISCARD , 客户端可以清空事务队列并放弃执行事务。例子:

localhost:0>multi"OK"localhost:0>set test abcd"QUEUED"localhost:0>discard"OK"localhost:0>get test"abc"

 

4、远程连接redis注意事项

   redis现在的版本开启redis-server后,redis-cli只能访问到127.0.0.1,因为在配置文件中固定了ip,因此需要修改redis.conf(有的版本不是这个文件名,只要找到相对应的conf后缀的文件即可)文件以下几个地方。1、bind 127.0.0.1改为 #bind 127.0.0.1   2、protected-mode yes 改为 protected-mode no

     指定配置文件运行:

./redis-server ../redis.conf

 远程连接的命令:

 

./redis-cli -p 6379 -h xxx.xxx.xxx

 

二、使用SpringCache集成redis

1、关于SpringCache

  从SpringFramework3.1版本开始,Spring给我们提供了一系列注解和接口规范来简化我们操作缓存代码量,几个核心接口如下:

  CacheManager: 该接口主要作用是获取缓存和获取缓存名称

SpringCache学习之操作redisSpringCache学习之操作redis
/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.cache;import java.util.Collection;import org.springframework.lang.Nullable;/** * Spring's central cache manager SPI. * Allows for retrieving named {@link Cache} regions. * * @author Costin Leau * @since 3.1 */public interface CacheManager {    /**     * Return the cache associated with the given name.     * @param name the cache identifier (must not be {@code null})     * @return the associated cache, or {@code null} if None found     */    @Nullable    Cache getCache(String name);    /**     * Return a collection of the cache names known by this manager.     * @return the names of all caches known by the cache manager     */    Collection<String> getCacheNames();}
View Code

  在这里面最核心的接口当然是Cache:

SpringCache学习之操作redisSpringCache学习之操作redis
/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.cache;import java.util.concurrent.Callable;import org.springframework.lang.Nullable;/** * Interface that defines common cache operations. * * <b>Note:</b> Due to the generic use of caching, it is recommended that * implementations allow storage of <tt>null</tt> values (for example to * cache methods that return {@code null}). * * @author Costin Leau * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.1 */public interface Cache {    /**     * Return the cache name.     */    String getName();    /**     * Return the underlying native cache provider.     */    Object getNativeCache();    /**     * Return the value to which this cache maps the specified key.     * <p>Returns {@code null} if the cache contains no mapping for this key;     * otherwise, the cached value (which may be {@code null} itself) will     * be returned in a {@link ValueWrapper}.     * @param key the key whose associated value is to be returned     * @return the value to which this cache maps the specified key,     * contained within a {@link ValueWrapper} which may also hold     * a cached {@code null} value. A straight {@code null} being     * returned means that the cache contains no mapping for this key.     * @see #get(Object, Class)     */    @Nullable    ValueWrapper get(Object key);    /**     * Return the value to which this cache maps the specified key,     * generically specifying a type that return value will be cast to.     * <p>Note: This variant of {@code get} does not allow for differentiating     * between a cached {@code null} value and no cache entry found at all.     * Use the standard {@link #get(Object)} variant for that purpose instead.     * @param key the key whose associated value is to be returned     * @param type the required type of the returned value (may be     * {@code null} to bypass a type check; in case of a {@code null}     * value found in the cache, the specified type is irrelevant)     * @return the value to which this cache maps the specified key     * (which may be {@code null} itself), or also {@code null} if     * the cache contains no mapping for this key     * @throws IllegalStateException if a cache entry has been found     * but failed to match the specified type     * @since 4.0     * @see #get(Object)     */    @Nullable    <T> T get(Object key, @Nullable Class<T> type);    /**     * Return the value to which this cache maps the specified key, obtaining     * that value from {@code valueLoader} if necessary. This method provides     * a simple substitute for the conventional "if cached, return; otherwise     * create, cache and return" pattern.     * <p>If possible, implementations should ensure that the loading operation     * is synchronized so that the specified {@code valueLoader} is only called     * once in case of concurrent access on the same key.     * <p>If the {@code valueLoader} throws an exception, it is wrapped in     * a {@link ValueRetrievalException}     * @param key the key whose associated value is to be returned     * @return the value to which this cache maps the specified key     * @throws ValueRetrievalException if the {@code valueLoader} throws an exception     * @since 4.3     */    @Nullable    <T> T get(Object key, Callable<T> valueLoader);    /**     * Associate the specified value with the specified key in this cache.     * <p>If the cache previously contained a mapping for this key, the old     * value is replaced by the specified value.     * @param key the key with which the specified value is to be associated     * @param value the value to be associated with the specified key     */    void put(Object key, @Nullable Object value);    /**     * Atomically associate the specified value with the specified key in this cache     * if it is not set already.     * <p>This is equivalent to:     * <pre><code>     * Object existingValue = cache.get(key);     * if (existingValue == null) {     *     cache.put(key, value);     *     return null;     * } else {     *     return existingValue;     * }     * </code></pre>     * except that the action is performed atomically. While all out-of-the-box     * {@link CacheManager} implementations are able to perform the put atomically,     * the operation may also be implemented in two steps, e.g. with a check for     * presence and a subsequent put, in a non-atomic way. Check the documentation     * of the native cache implementation that you are using for more details.     * @param key the key with which the specified value is to be associated     * @param value the value to be associated with the specified key     * @return the value to which this cache maps the specified key (which may be     * {@code null} itself), or also {@code null} if the cache did not contain any     * mapping for that key prior to this call. Returning {@code null} is therefore     * an indicator that the given {@code value} has been associated with the key.     * @since 4.1     */    @Nullable    ValueWrapper putIfAbsent(Object key, @Nullable Object value);    /**     * Evict the mapping for this key from this cache if it is present.     * @param key the key whose mapping is to be removed from the cache     */    void evict(Object key);    /**     * Remove all mappings from the cache.     */    void clear();    /**     * A (wrapper) object representing a cache value.     */    @FunctionalInterface    interface ValueWrapper {        /**         * Return the actual value in the cache.         */        @Nullable        Object get();    }    /**     * Wrapper exception to be thrown from {@link #get(Object, Callable)}     * in case of the value loader callback failing with an exception.     * @since 4.3     */    @SuppressWarnings("serial")    class ValueRetrievalException extends RuntimeException {        @Nullable        private final Object key;        public ValueRetrievalException(@Nullable Object key, Callable<?> loader, Throwable ex) {            super(String.format("Value for key '%s' could not be loaded using '%s'", key, loader), ex);            this.key = key;        }        @Nullable        public Object getKey() {            return this.key;        }    }}
View Code

  该接口定义了操作缓存的最基本行为

  同时Spring给我们提供了一些默认的缓存实现 比如说:JDK java.util.concurrent.ConcurrentMap,ehcache2.x , Gemfire cache, guava等

2、几个重要的注解

   @EnableCaching:用于开启缓存注解,通常需要和@Configuration使用

   @Cacheable 该注解的意思为:读缓存中的值,如果没有该值,那么将执行注解对应的方法并将方法返回结果存入缓存

   使用示例:

SpringCache学习之操作redisSpringCache学习之操作redis
@Cacheable(cacheNames="books", key="#isbn")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)@Cacheable(cacheNames="books", key="#isbn.rawNumber")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
View Code

   有些时候我们希望根据条件将对应数据存入缓存,可以这么写:

SpringCache学习之操作redisSpringCache学习之操作redis
@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")public Book findBook(String name)
View Code

   示例中:condition条件为true时,才存入缓存,unless属性是针对本次查询结果筛选。注意当表达式为true时的结果都不会存入缓存,  #result 代表了方法的返回结果

 

 

     @CacheEvict 触发Cache接口中的evict方法,相当于移除key对应的值

SpringCache学习之操作redisSpringCache学习之操作redis
@CacheEvict(cacheNames="books", allEntries=true,beforeInvocation=true)public void loadBooks(InputStream batch)
View Code

  beforeInvocation属性表明是否在执行方法之前清除缓存,allEntries属性会删除缓存下的所有数据,另外如果该值为true时就不能和key同时使用了

 

    @CachePut 执行方法并更新缓存

SpringCache学习之操作redisSpringCache学习之操作redis
@CachePut(cacheNames="book", key="#isbn")public Book updateBook(ISBN isbn, BookDescriptor descriptor)
View Code

   这些缓存注解的幕后英雄当然是我们的AOP啦

3、缓存注解中的SpringEL表达式

  springEL可以运用在我们的cache注解当中,比如说其中key属性 condition属性等,其中#result只能在unless属性中使用这点比较特殊,在这里我贴出官网的列表:

DescriptionExample

The name of the method being invoked

#root.methodName

The method being invoked

#root.method.name

The target object being invoked

#root.target

The class of the target being invoked

#root.targetClass

The arguments (as array) used for invoking the target

#root.args[0]

Collection of caches against which the current method is executed

#root.caches[0].name

Name of any of the method arguments. If for some reason the names are not available (e.g. no debug information), the argument names are also available under the #a<#arg> where #arg stands for the argument index (starting from 0).

#iban or #a0 (one can also use #p0 or #p<#arg>notation as an alias).

The result of the method call (the value to be cached). Only available in unlessexpressions, cache putexpressions (to compute the key), or cache evictexpressions (when beforeInvocation is false). For supported wrappers such as Optional#resultrefers to the actual object, not the wrapper.

#result

4、代码集成示例

该代码是基于spring与hibernate集成,请参考:这里

gradle配置:

SpringCache学习之操作redisSpringCache学习之操作redis
compile 'org.springframework.data:spring-data-redis:2.0.6.RELEASE'    // https://mvnrepository.com/artifact/redis.clients/jedis    compile group: 'redis.clients', name: 'jedis', version: '2.9.0'// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.5'// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5'
View Code

 

1.创建RedisConfig:

SpringCache学习之操作redisSpringCache学习之操作redis
package com.bdqn.lyrk.ssh.study.config;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.connection.RedisStandaloneConfiguration;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;@Configuration@EnableCachingpublic class RedisConfig {    /**     * 创建redisConnectionFactory     * @return     */    @Bean    public RedisConnectionFactory redisConnectionFactory() {        /*            设置相关配置         */        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();        configuration.setPort(6379);        configuration.setHostName("localhost");        configuration.setDatabase(0);        JedisConnectionFactory jedisConnectionFactory =                new JedisConnectionFactory(configuration);        return jedisConnectionFactory;    }    @Bean    public StringRedisTemplate stringRedisTemplate() {        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();        stringRedisTemplate.setConnectionFactory(redisConnectionFactory());        return stringRedisTemplate;    }    @Bean    public RedisCacheManager cacheManager() {        /*            配置json序列化方式         */        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().                serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(                        new GenericJackson2JsonRedisSerializer()));        return RedisCacheManager.builder(redisConnectionFactory()).                transactionAware().cacheDefaults(cacheConfiguration).build();    }}
View Code

2.创建StudentService

SpringCache学习之操作redisSpringCache学习之操作redis
package com.bdqn.lyrk.ssh.study.service;import com.bdqn.lyrk.ssh.study.entity.StudentEntity;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.orm.hibernate5.HibernateTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Servicepublic class StudentService {    @Autowired    private HibernateTemplate hibernateTemplate;    @Transactional    public int save(StudentEntity studentEntity) {        hibernateTemplate.save(studentEntity);        return studentEntity.getId();    }    @Cacheable(key = "#id", cacheNames = "student", cacheManager = "cacheManager", condition = "#id==1")    public StudentEntity listStudents(Integer id) {        return hibernateTemplate.get(StudentEntity.class, id);    }    @Transactional    @CachePut(key = "#id", cacheNames = "student", cacheManager = "cacheManager")    public StudentEntity updateStudent(Integer id) {        StudentEntity studentEntity = new StudentEntity();        studentEntity.setId(id);        studentEntity.setStuName("tests");        studentEntity.setPassword("password");        hibernateTemplate.update(studentEntity);        return studentEntity;    }    @CacheEvict(key = "#id", cacheNames = "student")    @Transactional    public StudentEntity deleteStudent(Integer id) {        StudentEntity studentEntity = hibernateTemplate.load(StudentEntity.class, id);        hibernateTemplate.delete(studentEntity);        return studentEntity;    }}
View Code

3.Main方法:

SpringCache学习之操作redisSpringCache学习之操作redis
package com.bdqn.lyrk.ssh.study;import com.bdqn.lyrk.ssh.study.config.AppConfig;import com.bdqn.lyrk.ssh.study.service.StudentService;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import java.io.IOException;public class Main {    public static void main(String[] args) throws IOException {        AnnotationConfigApplicationContext applicationContext =                new AnnotationConfigApplicationContext(AppConfig.class);        StudentService studentService =                applicationContext.getBean(StudentService.class);        studentService.updateStudent(1);        System.out.println(studentService.listStudents(1).getStuName());        studentService.deleteStudent(1);    }}
View Code

运行结果:

SpringCache学习之操作redis

 

我们可以看到:第二次查询时并没有输出Hibernate的执行的sql,说明这个是从redis缓存中读取的。 

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表