概述

本文内容主要

  • 关于spring-redis
  • 关于redis的key设计
  • redis的基本数据结构
  • 介绍redis与springboot的整合
  • sringboot中的redistemplate的使用

之前看了很多博客,大都都只是粗略的介绍,这里想要记录的全面一些,也算是一个学习的过程

首发于我的个人博客:janti的个人博客

关于spring-redis

spring-data-redis针对jedis提供了如下功能:

1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类

2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口

ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作 3. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations: BoundValueOperations
BoundSetOperations
BoundListOperations
BoundSetOperations
BoundHashOperations 4. 将事务操作封装,有容器控制。 5. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer) JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。 StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。 JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】 OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

如果你的数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer而不是JdkSerializationRedisSerializer。

关于key的设计

key的存活时间:

无论什么时候,只要有可能就利用key超时的优势。一个很好的例子就是储存一些诸如临时认证key之类的东西。当你去查找一个授权key时——以OAUTH为例——通常会得到一个超时时间。

这样在设置key的时候,设成同样的超时时间,Redis就会自动为你清除。

关系型数据库的redis

1: 把表名转换为key前缀 如, tag:

2: 第2段放置用于区分区key的字段--对应mysql中的主键的列名,如userid

3: 第3段放置主键值,如2,3,4...., a , b ,c

4: 第4段,写要存储的列名

例:user:userid:9:username

Redis的数据类型

String字符串

  • string是redis最基本的类型,一个key对应一个value。
  • string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
  • string类型是Redis最基本的数据类型,一个键最大能存储512MB。
  • String类型的操作参考

链表

  • redis列表是简单的字符串列表,排序为插入的顺序。列表的最大长度为2^32-1。

  • redis的列表是使用链表实现的,这意味着,即使列表中有上百万个元素,增加一个元素到列表的头部或尾部的操作都是在常量的时间完成。

  • 可以用列表获取最新的内容(像帖子,微博等),用ltrim很容易就会获取最新的内容,并移除旧的内容。

  • 用列表可以实现生产者消费者模式,生产者调用lpush添加项到列表中,消费者调用rpop从列表中提取,如果没有元素,则轮询去获取,或者使用brpop等待生产者添加项到列表中。

  • List类型的操作参考

集合

  • redis集合是无序的字符串集合,集合中的值是唯一的,无序的。可以对集合执行很多操作,例如,测试元素是否存在,对多个集合执行交集、并集和差集等等。
  • 我们通常可以用集合存储一些无关顺序的,表达对象间关系的数据,例如用户的角色,可以用sismember很容易就判断用户是否拥有某个角色。
  • 在一些用到随机值的场合是非常适合的,可以用 srandmember/spop 获取/弹出一个随机元素。

    同时,使用@EnableCaching开启声明式缓存支持,这样就可以使用基于注解的缓存技术。注解缓存是一个对缓存使用的抽象,通过在代码中添加下面的一些注解,达到缓存的效果。
  • Set类型的操作参考

ZSet 有序集合

  • 有序集合由唯一的,不重复的字符串元素组成。有序集合中的每个元素都关联了一个浮点值,称为分数。可以把有序看成hash和集合的混合体,分数即为hash的key。

  • 有序集合中的元素是按序存储的,不是请求时才排序的。

  • ZSet类型的操作类型

Hash-哈希

  • redis的哈希值是字符串字段和字符串之间的映射,是表示对象的完美数据类型。

  • 哈希中的字段数量没有限制,所以可以在你的应用程序以不同的方式来使用哈希。

  • Hash类型的操作参考

springboot 与redis的整合

pom文件

依赖如下:

   <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/>
</parent> <dependencies>
<!-- spring boot 配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> </dependencies>

application.properties

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0

redisTemplate的配置

新建一个redisConfig类,进行相关bean的配置:

package com.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; /**
* @author janti
* reids 相关bean的配置
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport { /**
* 选择redis作为默认缓存工具
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
return rcm;
} /**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om); // 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer()); // 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet(); return template;
} /**
* 对hash类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
} /**
* 对redis字符串类型数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
} /**
* 对链表类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
} /**
* 对无序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
} /**
* 对有序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
  • spring-redis中使用了RedisTemplate来进行redis的操作,通过泛型的K和V设置键值对的对象类型。这里使用了string作为key的对象类型,值为Object。

  • 对于Object,spring-redis默认使用了jdk自带的序列化,不推荐使用默认了。所以使用了json的序列化方式

  • 对spring-redis对redis的五种数据类型也有支持

  • HashOperations:对hash类型的数据操作

  • ValueOperations:对redis字符串类型数据操作

  • ListOperations:对链表类型的数据操作

  • SetOperations:对无序集合类型的数据操作

  • ZSetOperations:对有序集合类型的数据操作

redis操作的工具类

package com.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream; @Component
public class RedisService {
@Autowired
private RedisTemplate<String, String> redisTemplate; /**
* 默认过期时长,单位:秒
*/
public static final long DEFAULT_EXPIRE = 60 * 60 * 24; /**
* 不设置过期时长
*/
public static final long NOT_EXPIRE = -1; public boolean existsKey(String key) {
return redisTemplate.hasKey(key);
} /**
* 重名名key,如果newKey已经存在,则newKey的原值被覆盖
*
* @param oldKey
* @param newKey
*/
public void renameKey(String oldKey, String newKey) {
redisTemplate.rename(oldKey, newKey);
} /**
* newKey不存在时才重命名
*
* @param oldKey
* @param newKey
* @return 修改成功返回true
*/
public boolean renameKeyNotExist(String oldKey, String newKey) {
return redisTemplate.renameIfAbsent(oldKey, newKey);
} /**
* 删除key
*
* @param key
*/
public void deleteKey(String key) {
redisTemplate.delete(key);
} /**
* 删除多个key
*
* @param keys
*/
public void deleteKey(String... keys) {
Set<String> kSet = Stream.of(keys).map(k -> k).collect(Collectors.toSet());
redisTemplate.delete(kSet);
} /**
* 删除Key的集合
*
* @param keys
*/
public void deleteKey(Collection<String> keys) {
Set<String> kSet = keys.stream().map(k -> k).collect(Collectors.toSet());
redisTemplate.delete(kSet);
} /**
* 设置key的生命周期
*
* @param key
* @param time
* @param timeUnit
*/
public void expireKey(String key, long time, TimeUnit timeUnit) {
redisTemplate.expire(key, time, timeUnit);
} /**
* 指定key在指定的日期过期
*
* @param key
* @param date
*/
public void expireKeyAt(String key, Date date) {
redisTemplate.expireAt(key, date);
} /**
* 查询key的生命周期
*
* @param key
* @param timeUnit
* @return
*/
public long getKeyExpire(String key, TimeUnit timeUnit) {
return redisTemplate.getExpire(key, timeUnit);
} /**
* 将key设置为永久有效
*
* @param key
*/
public void persistKey(String key) {
redisTemplate.persist(key);
} }

redis的key工具类

package com.util;

/**
* redisKey设计
*/
public class RedisKeyUtil { /**
* redis的key
* 形式为:
* 表名:主键名:主键值:列名
*
* @param tableName 表名
* @param majorKey 主键名
* @param majorKeyValue 主键值
* @param column 列名
* @return
*/
public static String getKeyWithColumn(String tableName,String majorKey,String majorKeyValue,String column){
StringBuffer buffer = new StringBuffer();
buffer.append(tableName).append(":");
buffer.append(majorKey).append(":");
buffer.append(majorKeyValue).append(":");
buffer.append(column);
return buffer.toString();
}
/**
* redis的key
* 形式为:
* 表名:主键名:主键值
*
* @param tableName 表名
* @param majorKey 主键名
* @param majorKeyValue 主键值
* @return
*/
public static String getKey(String tableName,String majorKey,String majorKeyValue){
StringBuffer buffer = new StringBuffer();
buffer.append(tableName).append(":");
buffer.append(majorKey).append(":");
buffer.append(majorKeyValue).append(":");
return buffer.toString();
}
}

如何使用?

测试代码

新建一个实体类:

package com.domain;

public class UserVo {

    public  static final String Table = "t_user";

    private String name;
private String address;
private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} @Override
public String toString() {
return "UserVo{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", age=" + age +
'}';
}
}

再新建一个测试类:

package com.config;

import com.domain.UserVo;
import com.service.RedisService;
import com.util.RedisKeyUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import java.util.Set;
import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; @RunWith(SpringRunner.class)
@SpringBootTest
public class RedisConfigTest { @Autowired
private StringRedisTemplate stringRedisTemplate; @Autowired
private RedisTemplate redisTemplate; @Resource
private ValueOperations<String,Object> valueOperations; @Autowired
private HashOperations<String, String, Object> hashOperations; @Autowired
private ListOperations<String, Object> listOperations; @Autowired
private SetOperations<String, Object> setOperations; @Autowired
private ZSetOperations<String, Object> zSetOperations; @Resource
private RedisService redisService; @Test
public void testObj() throws Exception{
UserVo userVo = new UserVo();
userVo.setAddress("上海");
userVo.setName("测试dfas");
userVo.setAge(123);
ValueOperations<String,Object> operations = redisTemplate.opsForValue();
redisService.expireKey("name",20, TimeUnit.SECONDS);
String key = RedisKeyUtil.getKey(UserVo.Table,"name",userVo.getName());
UserVo vo = (UserVo) operations.get(key);
System.out.println(vo);
} @Test
public void testValueOption( )throws Exception{
UserVo userVo = new UserVo();
userVo.setAddress("上海");
userVo.setName("jantent");
userVo.setAge(23);
valueOperations.set("test",userVo); System.out.println(valueOperations.get("test"));
} @Test
public void testSetOperation() throws Exception{
UserVo userVo = new UserVo();
userVo.setAddress("北京");
userVo.setName("jantent");
userVo.setAge(23);
UserVo auserVo = new UserVo();
auserVo.setAddress("n柜昂周");
auserVo.setName("antent");
auserVo.setAge(23);
setOperations.add("user:test",userVo,auserVo);
Set<Object> result = setOperations.members("user:test");
System.out.println(result);
} @Test
public void HashOperations() throws Exception{
UserVo userVo = new UserVo();
userVo.setAddress("北京");
userVo.setName("jantent");
userVo.setAge(23);
hashOperations.put("hash:user",userVo.hashCode()+"",userVo);
System.out.println(hashOperations.get("hash:user",userVo.hashCode()+""));
} @Test
public void ListOperations() throws Exception{
UserVo userVo = new UserVo();
userVo.setAddress("北京");
userVo.setName("jantent");
userVo.setAge(23);
// listOperations.leftPush("list:user",userVo);
// System.out.println(listOperations.leftPop("list:user"));
// pop之后 值会消失
System.out.println(listOperations.leftPop("list:user"));
}
}

注解缓存的使用

  • @Cacheable:在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;没有则调用方法并将方法返回值放进缓存。

  • @CachePut:将方法的返回值放到缓存中。

  • @CacheEvict:删除缓存中的数据。

最后所有的代码都被上传到我的github喜欢的话,给个start

参考:

Redis 学习(二) —— 数据类型及操作

安装参考

springboot之使用redistemplate优雅地操作redis的更多相关文章

  1. redistemplate优雅地操作redis redis 工具类

    参考:https://www.cnblogs.com/superfj/p/9232482.html redis 工具类 package com.service; import org.springfr ...

  2. 【快学springboot】14.操作redis之list

    前言 之前讲解了springboot(StringRedisTemplate)操作redis的string数据结构,这篇文章将会讲解list数据结构 list数据结构具有的操作 下图列出了redis ...

  3. 使用Spring Data Redis操作Redis(单机版)

    说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点.并且会与一些低版本的Sp ...

  4. springboot中,使用redisTemplate操作redis

    知识点: springboot中整合redis springboot中redisTemplate的使用 redis存数据时,key出现乱码问题 一:springboot中整合redis (1)pom. ...

  5. SpringBoot 使用RedisTemplate操作Redis

    新版: import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.T ...

  6. Java 使用Jedis和RedisTemplate操作Redis缓存(SpringBoot)

    package com.example.redis.controller; import com.example.redis.entity.User; import com.example.redis ...

  7. Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate

    1. 简介 当我们对redis的基本知识有一定的了解后,我们再通过实战的角度学习一下在SpringBoot环境下,如何优雅的使用redis. 我们通过使用SpringBoot内置的Redis注解(文章 ...

  8. redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)

    平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...

  9. springboot2.1.3 + redisTemplate + Lock 操作 redis 3.0.5

    近期在整合springboot + redis 的功能,本来想用原生的jedit api,最后想想有点 low,搜了一把,boot已经提供给我们操作的方法,那就是 使用 redisTemplate 或 ...

随机推荐

  1. 《面向对象程序设计(java)》第七周学习总结

    1.实验目的与要求 (1)进一步理解4个成员访问权限修饰符的用途: (2)掌握Object类的常用API用法: (3)掌握ArrayList类用法与常用API: (4)掌握枚举类使用方法: (5)结合 ...

  2. 2017-09-16 ADB Shell+Putty

    鼓捣电子词典的时候需要用到ADB Shell.一开始是用cmd.exe,结果发现它不能识别ANSI转义符,就换成了Putty,然后就可以正常使用了,还有彩色. 配置如下: Connection Typ ...

  3. CheckBox获取一组及全选

    获取一组CheckBox: jQuery: $(function () { $("input[name=names]").click(function () { //获得所有的na ...

  4. iOS app审核被拒申诉

    提交申诉理由之后不需要点击“提交审核”按钮,否则按照重新提交算,需要重新排队,且申诉会不起作用.

  5. 云笔记项目-补充JS面向对象编程基础知识

    简单介绍: 此部分知识为在做云笔记项目中补充,因为云笔记项目中涉及到前端js,里面写了很多js脚本,用到了创建js属性和方法,在js中直接声明的属性和方法最终都会变成window的对象,即其成为了全局 ...

  6. ubuntu安装gitlab-ci-runner、注册

    首先信任 GitLab 的 GPG 公钥: curl https://packages.gitlab.com/gpg.key 2> /dev/null | sudo apt-key add - ...

  7. 你不知道的JavaScript中,读书笔记

    七种内置类型 null, undefined, boolean, number, string, object, symbol typeof null === 'object' // true nul ...

  8. Linux上web服务器搭建

    安装php依赖包: yum -y install gcc gcc++ libxml2 libxml2-devel yum install gcc make gd-devel libjpeg-devel ...

  9. hdu 4714 树+DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714 本来想直接求树的直径,再得出答案,后来发现是错的. 思路:任选一个点进行DFS,对于一棵以点u为 ...

  10. NTFS(Windows)、ext4(RHEL6)和xfs(RHEL7)文件系统的误删除恢复和备份

    前言 对于误删除文件的设备,要马上停止任何写的操作,防止删除的文件被覆盖,导致数据丢失! 恢复NTFS文件系统下误删的文件 以Windows为例,市面上能恢复的工具不少,例如EasyRecovery. ...