一、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 somevalue
OK
> get mykey
"somevalue"

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

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

> mset a  b  c
OK
> mget a b c
) ""
) ""
) ""

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

> set mykey hello
OK
> exists mykey
(integer)
> del mykey
(integer)
> exists mykey
(integer)

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

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

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

  

 rpush mylist A
(integer)
> rpush mylist B
(integer)
> lpush mylist first
(integer)
> lrange mylist -
) "first"
) "A"
) "B"

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

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

> hmset user: username antirez birthyear  verified
OK
> hget user: username
"antirez"
> hget user: birthyear
""
> hgetall user:
) "username"
) "antirez"
) "birthyear"
) ""
) "verified"
) ""

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

> sadd myset
(integer)
> smembers myset
.
.
.

  3、redis中的事务

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

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

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

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

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

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

localhost:>multi
"OK" localhost:>set test abcd
"QUEUED" localhost:>discard
"OK" localhost:>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  -h xxx.xxx.xxx

二、使用SpringCache集成redis

1、关于SpringCache

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

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

/*
* 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(); }

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

/*
* 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;
}
} }

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

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

2、几个重要的注解

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

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

   使用示例:

@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)

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

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")
public Book findBook(String name)

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

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

@CacheEvict(cacheNames="books", allEntries=true,beforeInvocation=true)
public void loadBooks(InputStream batch)

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

    @CachePut 执行方法并更新缓存

@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor)

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

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

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

Description Example

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配置:

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'

1.创建RedisConfig:

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
@EnableCaching
public 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();
}
}

2.创建StudentService

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; @Service
public 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;
}
}

3.Main方法:

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);
}
}

运行结果:

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

SpringCache学习之操作redis的更多相关文章

  1. 尚硅谷redis学习11-jedis操作redis

    前面学习了redis的知识后,下面学习一下如何在java中通过jedis操作redis. 所需jar包:commons-pool-xxxx.jar,jedis-xxx.jar 下面看一下常用操作: 1 ...

  2. Python学习之==>操作Redis

    一.redis简介 1.非关系型数据库 2.数据全部是存在内存里面 3.性能非常好,每秒支持30w次读写 4.可以通过备份数据库,把数据存到磁盘上来实现数据的持久化 二.操作redis 1.strin ...

  3. python学习之操作redis

    一.Redis安装网上很多可以查找 二.redis-py的安装,使用命令pip install redis. 安装过程中如果产生连接超时的错误,可以使用国内镜像参考如下 豆瓣:pip install ...

  4. Python基础学习六 操作Redis

    import redis r = redis.Redis(host=',db=1) #set get delete setex 都是针对string类型的 k-v # r.set('louis_ses ...

  5. 二、redis学习(java操作redis缓存的工具jedis)

  6. Python操作redis学习系列之(集合)set,redis set详解 (六)

    # -*- coding: utf-8 -*- import redis r = redis.Redis(host=") 1. Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合 ...

  7. redis学习 (key)键,Python操作redis 键 (二)

    # -*- coding: utf-8 -*- import redis #这个redis 连接不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. delete ...

  8. Python学习笔记(五)之Python操作Redis、mysql、mongodb数据库

    操作数据库 一.数据库 数据库类型主要有关系型数据库和菲关系型数据库. 数据库:用来存储和管理数的仓库,数据库是通过依据“数据结构”将数据格式化,以记录->表->库的关系存储.因此数据查询 ...

  9. Python进阶学习_连接操作Redis数据库

    安装导入第三方模块Redis pip3 install redis import redis 操作String类型 """ redis 基本命令 String set(n ...

随机推荐

  1. java 1.7新特性

    try( ... ){ ... } catch(xxx e){ ... } java1.7特性,叫做try-with-resource,实现了AutoCloseable接口的实例可以放在try(... ...

  2. PHP环境手动搭建wamp-----Apache+MySQL+PHP

    首先下载分别下载Apache+MySQL+PHP. 然后分别解压到文件夹中. 1.安装Apache 1)检查80端口是否占用 说明:apache软件占用80软件,在计算机中一个端口只能被一个软件占用 ...

  3. Table点击某个td获取当前列的头名称

    jq代码: $("td").click(function () { var tdHtml = $(this).attr("html"); var index = ...

  4. Python爬虫基本原理

    爬虫基本原理 1. 什么是爬虫 请求网站并提取数据的自动化程序. 2. 爬虫基本流程 发起请求 通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待 ...

  5. 多台linux主机之间建立免密通信

    多台linux主机之间设置免密通信 例:A 向 B设置免密通信 第一步 A生成密钥对 ssh-keygen -t rsa -t 指定秘钥的类型 rsa 秘钥类型 密钥目录:/root/.ssh/(如果 ...

  6. jmeter入门(02)测试报告各项指标含义

    一.名词定义(时间单位ms) 1.聚合报告 Sample:本次测试场景共运行多少个请求: Average:平均响应时间: Median:统计意义上的响应时间中值: 90% line:所有线程中90%的 ...

  7. GIT入门笔记(16)- 分支创建和管理

    查看分支:git branch创建分支:git branch <name>切换分支:git checkout <name>创建+切换分支:git checkout -b < ...

  8. python、java实现二叉树,细说二叉树添加节点、深度优先(先序、中序、后续)遍历 、广度优先 遍历算法

    数据结构可以说是编程的内功心法,掌握好数据结构真的非常重要.目前基本上流行的数据结构都是c和c++版本的,我最近在学习python,尝试着用python实现了二叉树的基本操作.写下一篇博文,总结一下, ...

  9. java配置环境变量,无法也行javac问题

    最近换了公司,搭建开发环境的时候出了点小差错,写篇随笔记录下,下载jdk的时候要选择符合自己电脑的jdk版本,位数. 笔者之前下载的时候没注意下了个32bit的jdk,开发用eclipse的时候打不开 ...

  10. win10下安装Ubuntu16.04双系统

    其实我是不喜欢系统的,之前都是在win下面进行开发,现在来了个项目,经过各种环境的安装调研,最终选择在Ubuntu下面进行开发.之前想着为啥不在虚拟机里面安装Ubuntu进行操作呢,由于虚拟机的体验不 ...