上一篇博客:spring boot 1.5.4 集成Swagger2构建Restful API(十八)

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。

redis官网:https://redis.io/

redis中文网:http://www.redis.net.cn/

书籍参阅:《redis实战》

redis概述

Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为
STRING(字符串)、LIST(列表)、SET(集合)、HASH(散列)和ZSET(有序集合)
有一部分Redis命令对于这5种结构都是通用的,如DEL、TYPE、RENAME等;但也有一部分Redis命令只能对特定的一种或者两种结构使用;

一些数据库和缓存服务器的特性与功能


名称 类型 数据存储选项 查询类型 附加功能
Redis 使用内存存储(in-memory)的非关系数据库 字符串、列表、集合、散列表、有序集合 每种数据类型都有自己的专属命令,另外还有批量操作(bulk operation)和不完全(partial)的事务支持 发布与订阅,主从复制(master/slave replication),持久化,脚本(存储过程,stored procedure)
memcached 使用内存存储的键值缓存 键值之间的映射 创建命令、读取命令、更新命令、删除命令以及其他几个命令 为提升性能而设的多线程服务器
MySQL 关系数据库 每个数据库可以包含多个表,每个表可以包含多个行;可以处理多个表的视图(view);支持空间(spatial)和第三方扩展 SELECT、 INSERT、 UPDATE、 DELETE、函数、存储过程 支持ACID性质(需要使用InnoDB),主从复制和主主复制 (master/master replication)
PostgreSQL 关系数据库 每个数据库可以包含多个表,每个表可以包含多个行;可以处理多个表的视图;支持空间和第三方扩展;支持可定制类型 SELECT、 INSERT、 UPDATE、 DELETE、内置函数、自定义的存储过程 支持ACID性质,主从复制,由第三方支持的多主复制(multi-master replication)
MongoDB 使用硬盘存储(on-disk)的非关系文档存储 每个数据库可以包含多个表,每个表可以包含多个无schema(schema-less)的BSON文档 创建命令、读取命令、更新命令、删除命令、条件查询命令等 支持map-reduce操作,主从复制,分片,空间索引(spatial index)

==表格样式不是我能决定的,凑合看吧==

Redis提供的5种结构


结构类型 结构存储的值 结构的读写能力
STRING 可以是字符串、整数或者浮点数 对整个字符串或者字符串的其中一部分执行操作;对整数和浮点数执行自增(increment)或者自减(decrement)操作
LIST 一个链表,链表上的每个节点都包含了一个字符串 从链表的两端推入或者弹出元素;根据偏移量对链表进行修剪(trim);读取单个或者多个元素;根据值查找或者移除元素
SET 包含字符串的无序收集器(unordered collection),并且被包含的每个字符串都是独一无二、各不相同的 添加、获取、移除单个元素;检查一个元素是否存在于集合中;计算交集、并集、差集;从集合里面随机获取元素
HASH 包含键值对的无序散列表 添加、获取、移除单个键值对;获取所有键值对
ZSET(有序集合) 字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定 添加、获取、删除单个元素;根据分值范围(range)或者成员来获取元素

redis特性


源码简单 ,约23000行C语言源代码。

  1. 速度快
    Redis是用C语言实现的;Redis的所有数据存储在内存中,用于快速地读写访问。
  2. 持久化
    Redis的所有数据存储在内存中,对数据的更新将异步地保存到磁盘上;
    redis的持久化有两种方式:AOF与RDB两种模式
  3. 支持多种数据结构
    Redis支持五种数据结构:String、List、Set、Hash、Zset
  4. 支持多种编程语言
    Java、php、Python、Ruby、Lua、Node.js等
  5. 功能丰富
    除了支持五种数据结构之外,还支持缓存、事务、流水线、发布/订阅、消息队列等功能。
    发布/订阅模型: Redis支持创建发布和订阅通道,这样Redis客户端可以订阅任意的通道来进行数据消费,并且任何已订阅该通道的客户端可以发布数据。
  6. 主从复制
    主服务器(master)执行写入(增删改),从(slave)服务器执行查询。复制提供可伸缩性和可用性。任何一个slave宕机,其他的slave还可以提供数据访问。
  7. 虚拟内存
    Redis使用RAM作为内存式存储。但是,在内存不足的情况下,它使用虚拟内存来保存数据。
  8. 高可用及分布式
    Redis-Sentinel(v2.8)支持高可用
    Redis-Cluster(v3.0)支持分布式

redis部分命令

flushdb:清空当前数据库;
select [index]:选择索引数据库,index为索引值名,如:select 1;
del [key]:删除一条指定key的值;
keys *:查看数据库内所有的key;
flushall:清空所有数据库;
quit:退出客户端连接。
==友情提示:部分命令慎用,线上一定不能用==

redis安装

redis下载安装

  1. windows版本下载:https://github.com/MicrosoftArchive/redis/releases ,目前是redis-3.2.100版本。
    spring boot 1.5.9 整合redis_第1张图片
  2. 解压下载的zip压缩包:
    spring boot 1.5.9 整合redis_第2张图片
    Redis on Windows.docx:关于Redis的描述文档
    redis.windeows.conf:默认的配置文件
    RedisService.docx:安装手册
    redis-server.exe:redis服务启动执行文件
    redis-cli.exe:redis客户端启动执行文件
  3. 注册redis服务到本机系统中
    在当前redis解压文件目录下...\Redis-x64-3.2.100\,本机系统中注册服务:

redis-server --service-install redis.windows.conf --loglevel verbose
卸载服务:
redis-server --service-uninstall
启动Redis:
redis-server.exe
指定配置文件启动,适用于多个redis数据库的时候
redis-server.exe redis.windows.conf

停止Redis:
redis-server --service-stop

安装成功:
spring boot 1.5.9 整合redis_第3张图片
启动redis:
spring boot 1.5.9 整合redis_第4张图片

  1. redis客户端测试
    • 双击redis客户端执行文件:redis-cli.exe
    • 测试:ping
      image

redis桌面可视化工具

  • Redis可视化工具,RedisDesktopManager
    它是开源的,托管在github上:https://github.com/uglide/RedisDesktopManager
    spring boot 1.5.9 整合redis_第5张图片
    下载地址:https://redisdesktop.com/download
  • 安装:双击默认安装
  • 连接测试:
    spring boot 1.5.9 整合redis_第6张图片

redis Java客户端

redis支持的语言,可在官网查看!重点看下redis的java客户端jedis:

github地址:https://github.com/xetorthio/jedis

spring boot 整合redis

spring boot整合redis有两种方式:
其一:使用外部配置,通过jedis技术框架实现;
其二:通过spring boot提供的数据访问框架Spring Data Redis实现,它是基于Jedis的。

第一种方式,可以参考SSM框架整合jedis进行操作配置;重点是第二种实现方式!

spring data redis

通过spring boot中的redis自动配置类,关于redis自动配置类RedisAutoConfiguration.java

//排除redis自动配置注解
@EnableAutoConfiguration(exclude = RedisAutoConfiguration.class)

查看其源码:
spring boot 1.5.9 整合redis_第7张图片

spring boot在Spring Data Redis提供了两个模板:

  • RedisTemplate
  • StringRedisTemplate

RedisTemplate会使用JdkSerializationRedisSerializer处理数据,这意味着key和value都会通过Java进行序列化。
StringRedisTemplate默认会使用StringRedisSerializer处理数据。

要是操作字符串的话,用StringRedisTemplate就可以满足。但要是想要存储一个对象Object,我们就需要使用RedisTemplate,并对key采用String序列化方式,对value采用json序列化方式,这时候就需要对redisTemplate自定义配置,项目源码片段:

/**
     * 实例化 RedisTemplate 对象
     *
     * @return RedisTemplate
     */
    @Bean
    public RedisTemplate functionDomainRedisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        initDomainRedisTemplate(redisTemplate);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式
         * 
redisTemplate 序列化默认使用的jdkSerializeable, 存储二进制字节码, 导致key会出现乱码,所以自定义 * 序列化类 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate redisTemplate) { // 使用Jackson2JsonRedisSerialize 替换默认序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //// string结构的数据,设置value的序列化规则和 key的序列化规则 //StringRedisSerializer解决key中乱码问题。//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(new StringRedisSerializer()); //value乱码问题:Jackson2JsonRedisSerializer redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); //设置Hash结构的key和value的序列化方式 //redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer); //redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); }

RedisTempalte类API

方  法 子API接口 描  述
opsForValue() ValueOperations 操作具有简单值的条目
opsForList() ListOperations 操作具有list值的条目
opsForSet() SetOperations 操作具有set值的条目
opsForZSet() ZSetOperations 操作具有ZSet值(排序的set)的条目
opsForHash() HashOperations 操作具有hash值的条目
boundValueOps(K) BoundValueOperations 以绑定指定key的方式,操作具有简单值的条目
boundListOps(K) BoundListOperations 以绑定指定key的方式,操作具有list值的条目
boundSetOps(K) BoundSetOperations 以绑定指定key的方式,操作具有set值的条目
boundZSet(K) BoundZSetOperations 以绑定指定key的方式,操作具有ZSet值(排序的set)的条目
boundHashOps(K) BoundHashOperations 以绑定指定key的方式,操作具有hash值的条目

spring boot缓存管理

spring boot集成redis进行数据缓存功能;有两种实现:
1,通过在代码中调用redis API实现数据的CRUD;
【参考RedisUtils工具类,该工具类支持redis的其他业务场景】
2,通过在方法上添加缓存注解实现;
【重点介绍,只支持redis作为缓存管理时使用】

Spring 提供了很多缓存管理器,例如:

  • SimpleCacheManager
  • EhCacheCacheManager
  • CaffeineCacheManager
  • GuavaCacheManager
  • CompositeCacheManager
  • RedisCacheManager Spring Data提供的缓存管理器:RedisCacheManager

在Spring Boot中通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),默认情况下Spring Boot根据下面的顺序自动检测缓存提供者:

  • Generic
  • JCache (JSR-107)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Redis
  • Guava
  • Simple

因为之前已经配置了RedisTemplate了,Spring Boot就无法自动给RedisCacheManager设置RedisTemplate了,所以要自己配置CacheManager。


1, 修改RedisConfig配置类,添加@EnableCaching注解,并继承CachingConfigurerSupport,重写CacheManager 方法:

/**
 * 实例化 CacheManager 对象,指定使用RedisCacheManager作缓存管理
 *
 * @return CacheManager
 */
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    // 设置缓存过期时间(单位:秒),60秒
    rcm.setDefaultExpiration(120);
    return rcm;
}

Spring提供了如下注解来声明缓存规则:

  • @Cacheable triggers cache population
  • @cacheevict triggers cache eviction
  • @cacheput updates the cache without interfering with the method execution
  • @caching regroups multiple cache operations to be applied on a method
  • @cacheconfig shares some common cache-related settings at class-level
注 解 描 述
@Cacheable 表明Spring在调用方法之前,首先应该在缓存中查找方法的返回值。如果这个值能够找到,就会返回缓存的值。否则的话,这个方法就会被调用,返回值会放到缓存之中
@cacheput 表明Spring应该将方法的返回值放到缓存中。在方法的调用前并不会 检查缓存,方法始终都会被调用
@cacheevict 表明Spring应该在缓存中清除一个或多个条目
@caching 这是一个分组的注解,能够同时应用多个其他的缓存注解
@cacheconfig 可以在类层级配置一些共用的缓存配置

@Cacheable和@cacheput有一些共有的属性:

属  性 类  型 描  述
value String[] 要使用的缓存名称
condition String SpEL表达式,如果得到的值是false的话,不会将缓存应用到方法调用上
key String SpEL表达式,用来计算自定义的缓存key
unless String SpEL表达式,如果得到的值是true的话,返回值不会放到缓存之中

2, 通过注解@Cacheable,对数据进行缓存处理:
代码片段:

/**
     * 通过缓存注解,添加数据到redis中
     * 
实现数据缓存! * @param cat 对象 */ @Cacheable @RequestMapping(value = "/getCat/{catId}", method = RequestMethod.GET) @ResponseBody public Cat add(@PathVariable("catId") int catId){ return this.catService.getCat(catId); }

注意:Cat对象必须实现implements Serializable接口!
启动访问:http://127.0.0.1:8066/redis/getCat/1

java.lang.IllegalStateException: No cache could be resolved for 'Builder[public com.wyait.redis.pojo.Cat com.wyait.redis.controller.RedisCacheController.add(int)] caches=[] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'' using resolver 'org.springframework.cache.interceptor.SimpleCacheResolver@5e67a11d'. At least one cache should be provided per cache operation.
    at org.springframework.cache.interceptor.CacheAspectSupport.getCaches(CacheAspectSupport.java:244) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]

这个错误,是由于@Cacheable注解没有指定缓存名称导致的。加上value值,再试:

@Cacheable(value = "catCache")

测试访问成功!多次访问,走redis缓存。


3, redis缓存key生成策略

键的生成策略有两种,一种是默认策略,一种是自定义策略。

  • ----------------------------默认策略:

    If no params are given, return SimpleKey.EMPTY.
    If only one param is given, return that instance.
    If more the one param is given, return a SimpleKey containing all parameters.

    默认的key是通过KeyGenerator生成的,其默认策略如下:
    1.如果方法没有参数,则使用0作为key;
    2.如果只有一个参数的话则使用该参数作为key;
    3.如果参数多于一个则使用所有参数的hashcode作为key;

  • ----------------------------自定义策略:
    自定义策略是指我们通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用参数以及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。

之前在redisTemplate里设置了template.setKeySerializer(new StringRedisSerializer()),需要key是string类型。也可以使用SpEL表达式生成Key,
(SpEL表达式:http://itmyhome.com/spring/expressions.html)
返回结果需要是string类型(比如#root.methodName就是,#root.method不是String),通用办法是重写keyGenerator定制Key默认生成策略(按照缓存名称+id方式生成key,同时确保更新操作的时候,操作的是同一条数据),也可以在使用缓存注解时指定key:

/**
     * 指定key的生成策略
     * @return KeyGenerator
     */
    @Bean public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override public Object generate(Object target, Method method,
                    Object... params) {
                StringBuilder sb = new StringBuilder();
                String[] value = new String[1];
                // sb.append(target.getClass().getName());
                // sb.append(":" + method.getName());
                Cacheable cacheable = method.getAnnotation(Cacheable.class);
                if (cacheable != null) {
                    value = cacheable.value();
                }
                CachePut cachePut = method.getAnnotation(CachePut.class);
                if (cachePut != null) {
                    value = cachePut.value();
                }
                CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class);
                if (cacheEvict != null) {
                    value = cacheEvict.value();
                }
                sb.append(value[0]);
                //获取参数值
                for (Object obj : params) {
                    sb.append(":" + obj.toString());
                }
                return sb.toString();
            }
        };
    }

注意:
1,在使用缓存注解时,也可以指定统一规则的key
(比如:@Cacheable(value = "catCache", key = "#root.caches[0].name + ':' + #id"));
就可以不走KeyGenerator默认规则;同样可以实现,更新和查询都是同一个key的数据;
2,使用注解进行数据缓存,指定数据过期时间需要百度普及下!


4, 更新缓存数据

更新与删除Redis缓存需要用到@cacheput和@cacheevict。必须保证keyGenerator生成同一个key,否则更新的不是同一条的数据;

/**
     * 更新redis中的缓存数据
     *
#root. 是spEL表达式 *
如果参数是个对象,就通过“#对象.变量”获取到对应的key中需要的值;比如:#cat.id * @param id 主键 */ @CachePut(value = "catCache", key = "#root.caches[0].name + ':' + #id") @RequestMapping(value = "/updateCat", method = RequestMethod.POST) @ResponseBody public Cat update(@RequestParam int id){ System.out.println("==========请求参数:"+id); return this.catService.updateCat(id); }

5, 测试//TODO

wyait-redis项目源码:

github:https://github.com/wyait/project.git
码云: https://gitee.com/wyait/springboot1.5.4.git

spring boot系列文章:

spring boot 1.5.4 概述(一)

spring boot 1.5.4 入门和原理(二)

spring boot 1.5.4 之web开发(三)

spring boot 1.5.4 整合JSP(四)

spring boot 1.5.4 集成devTools(五)

spring boot 1.5.4 集成JdbcTemplate(六)

spring boot 1.5.4 集成spring-Data-JPA(七)

spring boot 1.5.4 配置文件详解(八)

spring boot 1.5.4 统一异常处理(九)

spring boot 1.5.4 定时任务和异步调用(十)

spring boot 1.5.4 整合log4j2(十一)

spring boot 1.5.4 整合 mybatis(十二)

spring boot 1.5.4 整合 druid(十三)

spring boot 1.5.4 之监控Actuator(十四)

spring boot 1.5.4 整合webService(十五)

spring boot 1.5.4 整合redis、拦截器、过滤器、监听器、静态资源配置(十六)

spring boot 1.5.4 整合rabbitMQ(十七)

spring boot 1.5.4 集成Swagger2构建Restful API(十八)

spring boot 1.5.9 整合redis(十九)