一、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. Scala 快速入门

     Scalable 编程语言 纯正的的面向对象语言 函数式编程语言 无缝的java互操作 scala之父 Martin Odersky 1. 函数式编程 函数式编程(functional progr ...

  2. nyoj 回文字符串

    回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当 ...

  3. vue mint-ui 三级地址联动

    我也是第一次写这种地址联动的 刚开始的时候 我还以为直接用select来写 后来公司的ios告知并不是这样的 他说应该时这样的 于是第一想法 赶紧找插件吧 但是找了一会未果  就问了公司大神 他刚开始 ...

  4. NodeJs实现自定义分享功能,获取微信授权+用户信息

    最近公司搞了个转盘抽奖的运营活动,入口放在了微信公众号里,好久没碰过微信了,刚拾起来瞬间感觉有点懵逼....似乎把之前的坑又都重新踩了一遍,虽然过程曲折,不过好在顺利完成了,而且印象也更加深刻了,抽时 ...

  5. Python内置函数(32)——all

    英文文档: all(iterable) Return True if all elements of the iterable are true (or if the iterable is empt ...

  6. linux下的Shell编程(8)自定义函数

    Shell Script中也可以使用自定义的函数,其语法形式如下: functionname() { - }

  7. Spring Security 入门(1-3-5)Spring Security - remember me!

    Remember-Me 功能 概述 Remember-Me 是指网站能够在 Session 之间记住登录用户的身份,具体来说就是我成功认证一次之后在一定的时间内我可以不用再输入用户名和密码进行登录了, ...

  8. EasyUI combobox下拉多选框的实现

    combobox实现下拉列表多选, 效果如下

  9. global文件中的application_start方法中做: 定时器

    <%@ Application Language="C#" %> <%@ import Namespace="System.Data" %&g ...

  10. Oracle12c在Win10上的安装配置实践

    1.环境 操作系统:Win10专业版(64位) 数据库:Oracle 12c Release 2(Version 12.2.0.1.0,64位) 2.下载Oracle12c oracle官网下载地址: ...