Redis与Spring Data Redis
阅读原文时间:2021年10月04日阅读:1

1.1介绍

官网:https://redis.io/

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

1.2特性

1.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

3.Redis支持数据的备份,是单线程的。

2.1下载

linux版下载地址如下:

https://redis.io/download

下载的文件是二进制的压缩包,适用于linux。在windows安装redis见2.3.

2.2在linux安装redis

把下载的压缩包上传到linux中,这里以centos7为例:

1)解压

tar -xzvf redis-4.0.8.tar.gz

2)安装

cd redis-4.0.8
make
cd src
make install PREFIX=/usr/local/redis

3)移动配置文件到安装目录

mkdir /usr/local/redis/etc
cd ..
mv redis.conf /usr/local/redis/etc

4)首次启动redis

cd /usr/local/redis/bin
./redis-server

看到下图说明安装成功

后期可使用下面的命令启动,使用配置文件启动redis

/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

5)设置redis后台启动

vi /usr/local/redis/etc/redis.conf

将daemonize no 改成daemonize yes,保存退出。

6)将redis加入到开机启动

vi /etc/rc.local  

在里面添加

/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

7)关闭redis服务

pkill redis

8)redis客户端连接测试(此时已默认开启了redis)

/usr/local/redis/bin/redis-cli

如果设置了密码,就要使用密码登录

/usr/local/redis/bin/redis-cli -h ip地址 -p 6379 -a 密码

设置密码的方式

在配置文件redis.conf中找到这行代码

# requirepass foobared

取消注释,后面设置密码,这是设置为1234。然后关闭服务再开启(关闭/开启见上)

requirepass 1234

9)设置允许外网访问

在配置文件redis.conf中把bind开始的代码注释掉,如下,同样需要重启服务:

#bind 127.0.0.1

2.3在windows安装redis

2.3.1下载与安装

下载网站:https://github.com/microsoftarchive/redis/releases。下载需要版本的msi文件。

下载后傻瓜式安装即可。

2.3.2使用

1)在安装目录下打开Redis服务配置文件,找到# requirepass foobared,在下面写requirepass 1234,用来配置密码

2)点击“开始”>右击“计算机”>选择“管理”。在左侧栏中依次找到并点击“计算机管理(本地)”>服务和应用程序>服务。再在右侧找到Redis名称的服务,查看启动情况。如未启动,则手动启动之。正常情况下,服务应该正常启动并运行了。

3)在redis安装目录,打开cmd窗口,输入redis-cli,可以看到连接上了redis,如图

4)再继续输入auth 1234验证密码,显示OK就可以进入redis,来操作redis了。

2.4可视化工具安装

当然也有对应的工具来连接redis数据库,这里使用Redis Desktop Manager。此工具直接安装在windows系统。

1)下载

官网下载:http://redisdesktop.com/download

网盘下载:链接:https://pan.baidu.com/s/1odEEq9O137I6pHuFZ0reCg 提取码:1235

2)安装

点击exe进行傻瓜式安装。安装完成会在桌面生成一个快捷方式。

3)使用

打开之后,点击左下角的连接redis服务来连接redis,连接之后就可以看到里面的数据。

3.1查看所有的key值keys

keys *

3.2添加值set

set key value
//示例
set name zhangsan

3.3获取key值get

get key
//示例
get name

3.4判断key是否存在exists

只要指定的key中有一个存在就返回1。

exists key
//示例
exists name age

3.5对key设置失效时间expire

当对key设置失效时间后,过了此时间,key就会自动删除。单位是秒。

expire key
//示例,10s失效
expire name 10

pexpire和expire类型,只不过其单位是毫秒。  

3.6获取key的剩余生存时间ttl

单位是秒,当key不在时返回-2,当key存在且没有设置剩余时间时返回-1。

ttl key
//示例
ttl name

pttl同ttl,返回值是毫秒。

3.7随机返回key值randomkey

随机返回一个key,但不删除

randomkey
//示例
randomkey

3.8修改key值rename

rename key newkey
//示例
rename name name1

3.9获取值的类型type

type key
//示例
type name

4.1String类型

设置
set name zhangsan
获取
get name

4.2List类型 

有序,可重复

从头部添加
lpush userLists zhangsan lisi wangwu zhaoliu
遍历list,可以指定起止索引
lrange userLists 0 -1
从尾部添加
rpush userList li123 hu123 zhao456
删除第一个元素
lpop userList
删除最后一个元素
rpop userList
获取元素的个数
llen userList

4.3Set类型

无序,不能重复

添加元素
sadd arr 1 3 4 7 4 3 6
显示所有的元素
smembers arr
返回元素的个数
scard arr
随机删除一个元素
spop arr
删除指定元素
srem arr 4

4.4Zset类型 

不可重复,元素根据分数有序

添加元素,指定每个元素的分值
zadd arr 10 zhangsan 9 lisi 12 wangwu 6 zhaoliu
查看所有元素,升序
zrange arr 0 -1
查看所有元素,降序并显示分数
zrevrange arr 0 -1 withscores
返回元素的个数
zcard arr
查看排名,降序的排名
zrank arr zhangsan
删除指定元素
zrem arr zhangsan

4.5Hash类型

value是一个map类型。

添加值
hset maps name zhangsan
获取值
hget maps name
遍历键值对
hgetall maps
删除某一个键值对
hdel maps name
判断key是否存在,不存在返回0,存在返回1
hexist maps name
获取所有的key
hkeys maps
获取所有的value
hvals maps

把内存中的数据存入磁盘,这个就是持久化的过程。

5.1快照

将某一时刻的所有数据都写入硬盘中,保存的文件是以.rdb形式结尾的文件,这种方式也称之为RDB方式,是默认开启持久化的方式。

5.1.1快照生成方式

1)客户端方式

第一种方式:bgsave指令

客户端使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时, redis会调用fork1来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。

第二种方式:save指令

客户端也可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令,此时在生成快照之前,redis服务处于阻塞状态。

5.2AOF

这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集。

开启aof方法:

vi /usr/local/redis/etc/redis.conf

把appendonly no改为yes

6.1环境准备

1)新建一个maven的java项目

2)导入坐标

redis.clients jedis 2.9.0

3)创建jedis对象测试连接

public class Test {
public static void main(String[] args) {
//创建jedis客户端对象
Jedis jedis = new Jedis("192.168.159.129");
//指定密码
jedis.auth("123456");

    //获取所有的key  
    Set<String> keys = jedis.keys("\*");  
    System.out.println(keys);

    //释放资源  
    jedis.close();  
}  

}

直接运行main函数,可以打印出所有的key值,说明连接成功。

6.2基本测试

创建一个测试类,配置redis服务,然后所有的测试方法就在这个类中进行。

public class RedisTest {

private Jedis jedis;

/\*\*  
 \* 运行之前执行,开始连接  
 \*/  
@Before  
public void before(){  
    jedis=new Jedis("192.168.159.129");  
    jedis.auth("123456");  
}

/\*\*  
 \* 运行之后执行,关闭连接  
 \*/  
@After  
public void after(){  
    jedis.close();  
}  

}

6.2.1string类型测试

@Test  
public void stringSet(){  
    jedis.set("name","hello world");  
}

@Test  
public void stringGet(){  
    String name = jedis.get("name");  
    System.out.println(name);  
}

6.2.2list类型测试

@Test  
public void listSet(){  
    jedis.lpush("lists","zhangsan","lisi","王五");  
    jedis.rpush("lists","李敏","李四","赵丽");  
}

@Test  
public void listGet(){  
    List<String> lists = jedis.lrange("lists", 0, -1);  
    System.out.println(lists);  
}

6.2.3set类型上测试

@Test
public void setSet(){
jedis.sadd("set","123","456","789","456","666");
}

@Test  
public void setGet(){  
    Set<String> set = jedis.smembers("set");  
    System.out.println(set);  
}

6.2.4zset类型测试

@Test
public void zsetSet(){
jedis.zadd("zset",10,"张三");
jedis.zadd("zset",12,"李四");
jedis.zadd("zset",8,"张虎");
}

@Test  
public void zsetGet(){  
    Set<String> set = jedis.zrange("zset",0,-1);  
    System.out.println(set);  
}

6.2.5hash类型测试

@Test
public void hashSet(){
jedis.hset("maps","name","张三");
jedis.hset("maps","age","20");
jedis.hset("maps","sex","男");
}

@Test  
public void hashGet(){  
    Map<String, String> maps = jedis.hgetAll("maps");  
    System.out.println(maps);  
}

7.1环境准备

1)创建一个springboot的项目

2)导入坐标

org.springframework.boot spring-boot-starter-data-redis

3)配置数据源

#配置redis服务
spring:
redis:
#配置redis的编号,redis有16个database,0~15
database: 0
#配置主机地址
host: 192.168.159.129
#配置redis端口号,默认是6379
port: 6379
#配置redis登录密码
password: 123456
#配置连接池信息
jedis:
pool:
#配置最大连接数
max-active: 8
#配置最大空闲连接数
max-idle: 8
#配置最大阻塞等待时间
max-wait: -1ms
#配置最小空闲连接数
min-idle: 0

7.2基本测试

在测试类中注入对象

//当存储的值是string类型时使用
@Autowired
private StringRedisTemplate stringRedisTemplate;

//当存储的值是对象类型时使用  
@Autowired  
private RedisTemplate redisTemplate;

7.2.1key的基本操作

//设值字段的超时时间,单位是秒,超过时间后redis会自动删除
@Test
public void keyTimeOut(){
stringRedisTemplate.expire("name",10, TimeUnit.SECONDS);
}
//判断key存在
@Test
public void keyIsExists(){
Boolean exists = stringRedisTemplate.hasKey("name");
System.out.println(exists);
}
//删除key
@Test
public void keyDelete(){
stringRedisTemplate.delete("name");
}

7.2.2string类型基本操作

//string类型的操作,使用opsForValue
@Test
public void stringSet(){
stringRedisTemplate.opsForValue().set("name","张三");
}
@Test
public void stringGet(){
String s = stringRedisTemplate.opsForValue().get("name");
System.out.println(s);
}

7.2.3list类型基本操作

//list类型的操作,使用opsForList
@Test
public void listSet(){
stringRedisTemplate.opsForList().leftPush("lists","zhangsan");
stringRedisTemplate.opsForList().leftPushAll("lists","李敏","李四","赵丽");
}
@Test
public void listGet(){
List lists = stringRedisTemplate.opsForList().range("lists",0,-1);
System.out.println(lists);
}

7.2.4set类型基本操作

//set类型的操作,使用opsForSet
@Test
public void setSet(){
stringRedisTemplate.opsForSet().add("set","123","456","789","456","666","999","啧啧啧");
}
@Test
public void setGet(){
Set set = stringRedisTemplate.opsForSet().members("set");
System.out.println(set);
}

7.2.5zset类型基本操作

//zset类型的操作,使用opsForZSet
@Test
public void zsetSet(){
stringRedisTemplate.opsForZSet().add("zset","张三",10);
stringRedisTemplate.opsForZSet().add("zset","李四",20);
stringRedisTemplate.opsForZSet().add("zset","王五",30);
}
@Test
public void zsetGet(){
Set set = stringRedisTemplate.opsForZSet().range("zset",0,-1);
System.out.println(set);
}

7.2.6hash类型基本操作

//hash类型的操作,使用opsForHash
@Test
public void hashSet(){
stringRedisTemplate.opsForHash().put("maps","name","张三");
stringRedisTemplate.opsForHash().put("maps","age","20");
stringRedisTemplate.opsForHash().put("maps","sex","男");
}
@Test
public void hashGet(){
Map maps = stringRedisTemplate.opsForHash().entries("maps");
System.out.println(maps);
}

7.3redisTemplate与stringRedisTemplate的区别

1)两者数据各自存,各自取,数据不互通。

2)序列化策略不同。RedisTemplate采用JDK的序列化策略,StringRedisTemplate采用String的序列化策略。

3)存储数据类型不同。StringRedisTemplate的key和value都是stringt类型,RedisTemplate的key和value都是object类型。

7.4定义常用工具类RedisUtil

以string类型为例,其他雷同。

package com.zys.redisdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
* @author zhongyushi
* @date 2020/9/12 16:30:30
* @dec redis工具类
*/
@Component
public class RedisUtil {

@Autowired  
private StringRedisTemplate stringRedisTemplate;

@Autowired  
private RedisTemplate redisTemplate;

/\*\*  
 \* string类型  
 \*/

//删除key  
public void deleteKey(String key) {  
    stringRedisTemplate.delete(key);  
}

//判断key存在  
public boolean keyIsExists(String key) {  
    return stringRedisTemplate.hasKey(key);  
}

//设置key失效时间,以秒为单位  
public void setKeyTimeOut(String key, long second) {  
    stringRedisTemplate.expire(key, second, TimeUnit.SECONDS);  
}

//设置值  
public void setValue(String key, String val) {  
    stringRedisTemplate.opsForValue().set(key, val);  
}

//获取值  
public String getValue(String key) {  
    return stringRedisTemplate.opsForValue().get(key);  
}

/\*\*  
 \* object类型  
 \*/  
//存入对象  
public void setObject(String key,Object obj){  
      redisTemplate.opsForValue().set(key,obj);  
}

//获取对象  
public Object getObject(String key){  
    return redisTemplate.opsForValue().get(key);  
}

//删除对象  
public void delObject(String key){  
    redisTemplate.delete(key);  
}

//设置对象过期时间  
public void setObjectTimeOut(String key,long second){  
    redisTemplate.expire(key,second,TimeUnit.SECONDS);  
}

//判断对象是否存在  
public boolean objectIsExists(String key) {  
    return redisTemplate.hasKey(key);  
}

}

虽然mybatis有自己的缓存,但是存在于应用服务器,那么使用redis做缓存是当前的趋势。

源码:https://github.com/zhongyushi-git/redis-demo.git

8.1项目准备

首先创建一个springboot的项目,包含mysql、mybatis和redis,且有基本的数据访问接口,sql脚本在项目根目录下。

注意:要实现缓存,每个实体对象必须实现序列化接口

8.2缓存的基本实现

1)获取spring创建的工厂

package com.zys.redisdemo.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

/**
* @author zhongyushi
* @date 2020/9/16 0016
* @dec 获取spring创建的工厂
*/
@Configuration
public class ApplicationContextUtil implements ApplicationContextAware {

private static ApplicationContext applicationContext;

//把非spring创建好的工厂赋值给applicationContext,applicationContext在这个应用中是唯一的  
@Override  
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
    this.applicationContext = applicationContext;  
}

//此创建好工厂后再获取对象  
public static Object getBean(String beanName){  
    return applicationContext.getBean(beanName);  
}  

}

此类的作用就是把非spring创建好的工厂赋值给applicationContext,然后spring再根据类名去获取对应的类。

2)redis缓存类,实现Cache

package com.zys.redisdemo.cache;

import com.zys.redisdemo.util.ApplicationContextUtil;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.concurrent.locks.ReadWriteLock;

/**
* @author zhongyushi
* @date 2020/9/16 0016
* @dec 配置redis缓存,使用redis作为缓存服务器,减轻mysql服务器的访问压力
*/
public class RedisCache implements Cache {

//是mybatis必须要求的,必写。此id是xml中的namespace的值  
private final String id;  
public RedisCache(String id){  
    this.id=id;  
}

//返回cache的唯一名称  
@Override  
public String getId() {  
    return this.id;  
}

//缓存存值  
@Override  
public void putObject(Object key, Object value) {  
    //id是namespace的值,key是方法名,value是查询的结果  
    getRedisTemplate().opsForHash().put(id, key.toString(), value);  
}

//缓存取值  
@Override  
public Object getObject(Object key) {  
    return getRedisTemplate().opsForHash().get(id, key.toString());  
}

//mybatis保留方法  
@Override  
public Object removeObject(Object key) {  
    return null;  
}

//清空缓存,在增删改时会自动调用  
@Override  
public void clear() {  
    getRedisTemplate().delete(id);  
}

//缓存的数量  
@Override  
public int getSize() {  
    return getRedisTemplate().opsForHash().size(id).intValue();  

  }

@Override  
public ReadWriteLock getReadWriteLock() {  
    return null;  
}

//获取RedisTemplate,不能通过注入的方式,原因是此类是由mybatis实例化的  
private RedisTemplate getRedisTemplate(){  
    //从上下文中获取redisTemplate  
    RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");  
    //设置key是string类型的序列  
    redisTemplate.setKeySerializer(new StringRedisSerializer());  
    //设置hashKey是string类型的序列  
    redisTemplate.setHashKeySerializer(new StringRedisSerializer());  
    return redisTemplate;  
}  

}

在这个类中,分别重写了缓存设置、获取和删除的方法,把数据放到redis中。但是在此类中无法直接注入RedisTemplate,此类是由mybatis实例化的,不是由工厂实例化的。但是可以通过applicationContext来获取。

3)开启缓存

在xml中使用mybatis来开启缓存,指定为自定义的类型


4)测试

启动项目,使用postman对接口进行测试。结果显示,对于两个查询的操作,第一次查询会从数据库获取,多次调用时就从redis中获取。对于删除操作,会把对应的缓存数据清除,实际上修改和添加也是一样。即增删改都会清空缓存,这里以删除为例,是mybatis的缓存机制的体现。

8.3缓存的问题(共享缓存)

在上一小节的实例中,简单的数据都可以通过redis进行缓存,对应的更新更新缓存只在单个表中,不会影响其他的表。但是如果多个表具有关联关系时,还使用这种方式,就会出现数据无法更新的问题。

在xml中使用cache标签,那么其缓存是相互独立的,对于多表关联时,可以使用cache-ref标签。

比如新建一个ErpMapper.xml,在其中使用此标签


在ErpMapper中指定了namespace是UserDao,那么不管是User表的数据发生变化还是Erp表数据发生变化,都会删除User的缓存数据,从而及时的更新用户数据。

8.4缓存优化

在查看缓存的时候,发现存入的hash的key很长,是可以进行优化的,使用md5对数据进行简化,会生成一个32位的16进制字符串。

1)在RedisCache类添加加密的方法

//给定的字符串进行md5加密,转为32位的16进制
private String md5AsHex(String key){
return DigestUtils.md5DigestAsHex(key.getBytes());
}

2)然后对key进行加密,见源码。

8.5常见的面试题

8.5.1缓存穿透(击穿)

定义:客户端查询了一个数据库中不存在的记录,导致缓存不能使用。

解决:mybatis的cache就解决了此问题,即使查询的数据不存在,也会放到缓存中,只不过value为null而已。

8.5.2缓存雪崩

定义:在系统运行的某一时刻,突然系统中的所有缓存全部失效,恰好在这一时刻有大量的请求,导致所有的缓存无法使用。以至于大量的请求去请求数据库,让数据库阻塞或挂起。

解决:

1)缓存失效的原因之一就是对缓存设置了失效的时间,那么这样的缓存可以设置永久生效,不设置缓存失效时间。

2)针对不同的业务做不同的超时时间。

9.1什么是session共享

session共享简单的来说就是把用户登录后的session根据用户的唯一主键放到redis里面,用户在访问分布的其他系统时先去redis中查看是否有这个用户的session信息,有的话就不用再次登录,没有就需要登录。它是基于应用的session共享。

9.2session共享的应用

1)添加session依赖

org.springframework.session spring-session-data-redis

2)在controller中的存储和获取session

package com.zys.redisdemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

@RestController
public class RedisController {

@GetMapping("/save")  
public String save(String name, HttpSession session) {  
    //向session中存储数据  
    session.setAttribute("name", name);  
    return name;  
}

@GetMapping("/get")  
public String get(HttpSession session) {  
    //从session中h获取数据  
    return "session中的数据" + session.getAttribute("name");  
}  

}

3)把这个项目打包,然后部署到本地的两个tomcat上,这里端口就用8080和8081。

4)测试。浏览器输入http://localhost:8080/redis/save?name=123,对session的name设置值,然后再输入http://localhost:8081/redis/save?get使用另一个服务器来获取存入的值,发现是可以取到的。实际上,在存入的时候,会把session中的数据存储到redis中,取的时候是去redis获取的,这就是redis的session共享,对特定的数据共享非常方便。

注意:使用redis的session共享时,只要session的内容发送变化,就要及时更新redis的内容。

10.1定义

Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis,  JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

spring-data-redis针对jedis提供了如下功能:
1)连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2)针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,如下:

boundValueOps:string简单K-V操作
boundSetOps:set类型数据操作
boundZSetOps:zset类型数据操作
boundHashOps:针对map类型的数据操作
boundListOps:针对list类型的数据操作

10.2基本用法

10.2.1环境准备

这里就直接在redis的项目中进行说明。

1)导入坐标,如果没有导入请先导入,如果已经导入此步可省略。

org.springframework.boot spring-boot-starter-data-redis

不难发现,此依赖和springboot整合redis的依赖是一样的,这也就证实了Spring-data-redis是对redis的封装,只能使用在springboot的项目中,不能用在spring的项目里面。

新建一个测试类,注入对象

//当存储的值是string类型时使用
@Autowired
private StringRedisTemplate stringRedisTemplate;

//当存储的值是对象类型时使用  
@Autowired  
private RedisTemplate redisTemplate;

10.2.2key的基本操作

key的基本操作和上面一样,再辞略。

10.2.3string类型基本操作

//string类型的操作,使用boundValueOps
@Test
public void stringSet(){
stringRedisTemplate.boundValueOps("name").set("张三");
}
@Test
public void stringGet(){
String s = stringRedisTemplate.boundValueOps("name").get();
System.out.println(s);
}

10.2.4list类型基本操作

//list类型的操作,使用boundListOps
@Test
public void listSet(){
stringRedisTemplate.boundListOps("lists").leftPush("zhangsan");
stringRedisTemplate.boundListOps("lists").leftPushAll("李敏","李四","赵丽");
}
@Test
public void listGet(){
List lists = stringRedisTemplate.boundListOps("lists").range(0,-1);
System.out.println(lists);
}

10.2.5set类型基本操作

//set类型的操作,使用boundSetOps
@Test
public void setSet(){
stringRedisTemplate.boundSetOps("set").add("123","456","789","456","666","999","啧啧啧");
}
@Test
public void setGet(){
Set set = stringRedisTemplate.boundSetOps("set").members();
System.out.println(set);
}

10.2.6zset类型基本操作

//zset类型的操作,使用boundZSetOps
@Test
public void zsetSet(){
stringRedisTemplate.boundZSetOps("zset").add("张三",10);
stringRedisTemplate.boundZSetOps("zset").add("李四",20);
stringRedisTemplate.boundZSetOps("zset").add("王五",30);
}
@Test
public void zsetGet(){
Set set = stringRedisTemplate.boundZSetOps("zset").range(0,-1);
System.out.println(set);
}

10.2.7hash类型基本操作

//hash类型的操作,使用boundHashOps
@Test
public void hashSet(){
stringRedisTemplate.boundHashOps("maps").put("name","张三");
stringRedisTemplate.boundHashOps("maps").put("age","20");
stringRedisTemplate.boundHashOps("maps").put("sex","男");
}
@Test
public void hashGet(){
Map maps = stringRedisTemplate.boundHashOps("maps").entries();
System.out.println(maps);
}

10.3工具类改写

package com.zys.redisdemo.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
* @author zhongyushi
* @date 2020/9/12 16:30:30
* @dec redis工具类
*/
@Component
public class RedisUtil {

@Autowired  
private StringRedisTemplate stringRedisTemplate;

@Autowired  
private RedisTemplate redisTemplate;

/\*\*  
 \* string类型  
 \*/

//删除key  
public void deleteKey(String key) {  
    stringRedisTemplate.delete(key);  
}

//判断key存在  
public boolean keyIsExists(String key) {  
    return stringRedisTemplate.hasKey(key);  
}

//设置key失效时间,以秒为单位  
public void setKeyTimeOut(String key, long second) {  
    stringRedisTemplate.expire(key, second, TimeUnit.SECONDS);  
}

//设置值  
public void setValue(String key, String val) {  
    stringRedisTemplate.boundValueOps(key).set(val);  
}

//获取值  
public String getValue(String key) {  
    return stringRedisTemplate.boundValueOps(key).get();  
}

/\*\*  
 \* object类型  
 \*/  
//存入对象  
public void setObject(String key,Object obj){  
    getRedisTemplate().boundValueOps(key).set(obj);  
}

//获取对象  
public Object getObject(String key){  
    return getRedisTemplate().boundValueOps(key).get();  
}

//删除对象  
public void delObject(String key){  
    getRedisTemplate().delete(key);  
}

//设置对象过期时间  
public void setObjectTimeOut(String key,long second){  
    getRedisTemplate().expire(key,second,TimeUnit.SECONDS);  
}

//判断对象是否存在  
public boolean objectIsExists(String key) {  
    return getRedisTemplate().hasKey(key);  
}

//获取RedisTemplate,把key进行string序列化,那么在库中就显示的原始的key值,否则就是16进制的值不方便。  
private RedisTemplate getRedisTemplate(){  
    //设置key是string类型的序列  
    redisTemplate.setKeySerializer(new StringRedisSerializer());  
    //设置hashKey是string类型的序列  
    redisTemplate.setHashKeySerializer(new StringRedisSerializer());  
    return redisTemplate;  
}  

}

此工具类进行对redisTemplate进行了优化,设置key序列化,以便查看库时方便。