Redis与Spring Data Redis

本文共 23,473 字,预计阅读时间 78 分钟

 


1.Redis概述

1.1介绍

官网:https://redis.io/

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

1.2特性

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

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

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

2.Redis下载与安装

2.1下载

linux版下载地址如下:

1
https://redis.io/download

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

2.2在linux安装redis

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

1)解压

1
tar -xzvf redis-4.0.8.tar.gz

2)安装

1
2
3
4
cd redis-4.0.8
make
cd src
make install PREFIX=/usr/local/redis

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

1
2
3
mkdir /usr/local/redis/etc
cd ..
mv redis.conf /usr/local/redis/etc

4)首次启动redis

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

看到下图说明安装成功

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

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

5)设置redis后台启动

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

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

6)将redis加入到开机启动

1
vi /etc/rc.local  

在里面添加

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

7)关闭redis服务

1
pkill redis

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

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

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

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

设置密码的方式

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

1
# requirepass foobared

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

1
requirepass 1234

9)设置允许外网访问

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

1
#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.redis基本指令

3.1查看所有的key值keys

1
keys *

3.2添加值set

1
2
3
set key value
//示例
set name zhangsan

3.3获取key值get

1
2
3
get key
//示例
get name

3.4判断key是否存在exists

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

1
2
3
exists key
//示例
exists name age

3.5对key设置失效时间expire

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

1
2
3
expire key
//示例,10s失效
expire name 10

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

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

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

1
2
3
ttl key
//示例
ttl name

pttl同ttl,返回值是毫秒。

3.7随机返回key值randomkey

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

1
2
3
randomkey
//示例
randomkey

3.8修改key值rename

1
2
3
rename key newkey
//示例
rename name name1

3.9获取值的类型type

1
2
3
type key
//示例
type name

4.不同类型的get和set指令

4.1String类型

1
2
3
4
设置
set name zhangsan
获取
get name

4.2List类型 

有序,可重复

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

4.3Set类型

无序,不能重复

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

4.4Zset类型 

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

1
2
3
4
5
6
7
8
9
10
11
12
添加元素,指定每个元素的分值
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类型。map的字段又分别是field和value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
添加值
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.redis持久化机制

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

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.java操作redis

6.1环境准备

1)新建一个maven的java项目

2)导入坐标

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

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.springboot操作redis

7.1环境准备

1)创建一个springboot的项目

2)导入坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

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<String> 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<String> 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<String> 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<Object, Object> 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);
    }


}
复制代码

8.redis缓存

虽然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来开启缓存,指定为自定义的类型

<!--使用mybatis开启redis缓存-->
<cache type="com.zys.redisdemo.cache.RedisCache"/>

4)测试

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

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

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

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

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

<!--多表关联关系的缓存处理-->
<cache-ref namespace="com.zys.redisdemo.dao.UserDao"/>

在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.redis的session共享

9.1什么是session共享

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

9.2session共享的应用

1)添加session依赖

 <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
</dependency>

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.Spring Data 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接口,如下:

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

10.2基本用法

10.2.1环境准备

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

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

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

不难发现,此依赖和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<String> 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<String> 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<String> 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<Object, Object> 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序列化,以便查看库时方便。

 

posted @   钟小嘿  阅读(790)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示