Java操作Redis

前言

传统(企业内部)软件:         比如工单系统、OA、CRM、ERP、CMDB、大学选课系统等,主要服务于企业内部用户群体

互联网软件:                  比如 微信、QQ、今日头条、抖音、优酷、百度、微信、京东、天猫、12306 等,可服务于广大互联网用户群体

互联网软件有以下 3 大突出特点:

  • 高并发 (同时访问量大)
  • 高可用 (网站任何时候都能访问)
  • 海量数据 (动态数据量大)

MySQL 支持最大并发是 2000/ 秒,如果我们把所有数据存储在 MySQL 中,单靠关系型数据库,无法支撑起 1 个互联网软件

由于互联网的这些特点,单纯的关系型数据库是扛不住的,那么这个时候就需要非关系型数据库的加入;

非关系型数据库是为了配合关系型数据库共同应对互联网产品问题而存在的,他们之间的关系是合作,而不是替代;

常见的 NoSQL 产品:

  • Redis
  • Mongodb

 

一、Redis 介绍

Redis(Remote Dictionary Server)是用C 语言开发的一个开源的高性能的键值对数据库。

它的所有数据都是保存在内存中的,这也就决定了其读写速度之快,是其它硬盘保存数据的系统所无法匹敌的。

官方曾经给出过一组测试数据,50 个并发执行 100000 个请求: 读的速度是 110000 次 /s,写的速度是 81000 次 /s。

正是由于其有着如此高的性能,所以 Redis 在企业中最大的一个应用是作为缓存服务器使用,当然它也可以作为数据存储和消息中间件来用。

 

二、Redis 常用命令

 Redis 采用键值对存储数据,键的类型只能是字符串,值支持 5 种数据类型;

  • 字符串:   普通字符串
  • hash:      适合存储对象
  • 列表:      有序可以重复
  • 集合:    无序不重复
  • 有序集合:有序不重复

1.String 字符串

字符串类型是 Redis 中最为基础的数据存储类型。

增加数据:set key value

127.0.0.1:6379> set name zhanggen
OK

获取数据:get key

127.0.0.1:6379> get name
"zhanggen"
127.0.0.1:6379> 

删除数据:del key

127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)

增加数据的时候设置有效时间:setex key 存活时间 (单位是 s) value

127.0.0.1:6379> setex name 5 zhanggen
OK
127.0.0.1:6379> get name
"zhanggen"
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> 

增加的时候判断 key 是否存在:setnx key value

127.0.0.1:6379> setnx name Martin
(integer) 1
127.0.0.1:6379> get name
"Martin"
127.0.0.1:6379> 

自增 (减) 操作:

incr/decr key 

127.0.0.1:6379> set age 19
OK
127.0.0.1:6379> incr age
(integer) 20
127.0.0.1:6379> decr age
(integer) 19
127.0.0.1:6379> 

incrby/decrby key step

127.0.0.1:6379> incrby age 3
(integer) 22
127.0.0.1:6379> decrby age 3
(integer) 19
127.0.0.1:6379> 

 

2.Hash 哈希

Hash 类型极其类似于 Java 中的 Map,值里面可以存放一组组的键值对,该类型非常适合于存储对象类型的信息。

增加数据:hset key hkey hvalue

127.0.0.1:6379> hset student1 name zhanggen
(integer) 1
127.0.0.1:6379> hset student1 age 18
(integer) 1
127.0.0.1:6379> hset student1 sex man
(integer) 1

获取数据:hget key hkey

127.0.0.1:6379> hget student1 name
"zhanggen"
127.0.0.1:6379> hget student1 age
"18"
127.0.0.1:6379> hget student1 sex
"man"
127.0.0.1:6379> 

获取 hash 的所有键 hkey:hkeys key

127.0.0.1:6379> hkeys student1
1) "name"
2) "age"
3) "sex"

获取 hash 所有值 hvalue: hvals key

127.0.0.1:6379> hvals student1
1) "zhanggen"
2) "18"
3) "man"
127.0.0.1:6379> 

删除数据(单个): hdel key hkey

127.0.0.1:6379> hdel student1 sex
(integer) 1
127.0.0.1:6379> hkeys student1
1) "name"
2) "age"

删除数据(所有): del key

127.0.0.1:6379> del student1
(integer) 1
127.0.0.1:6379> hkeys student1
(empty array)
127.0.0.1:6379> 

 

3.List 列表

List 类型底层是一个双向字符串链表,里面的元素是有序可重复的,我们可以从链表的任何一端进行元素的增删

添加数据:lpush(rpush) key value

127.0.0.1:6379> lpush list zhanggen
(integer) 1
127.0.0.1:6379> lpush list lisi
(integer) 2
127.0.0.1:6379> rpush list wangwu

查询数据:lrange key [开始索引 结束索引]

127.0.0.1:6379> lrange list 0 -1
1) "lisi"
2) "zhanggen"
3) "wangwu"

列表长度:llen key

127.0.0.1:6379> llen list
(integer) 1

删除数据:lpop(rpop) key value

127.0.0.1:6379> lpop list
"lisi"
127.0.0.1:6379> rpop list
"wangwu"

移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止:BRPOP key timeout

 

4.Set 集合

Set 类型底层是一张 hash 表,里面的元素是无序的,不可重复的。

添加数据:sadd key value

127.0.0.1:6379> sadd userList zhangsan
(integer) 1
127.0.0.1:6379> sadd userList lisi
(integer) 1
127.0.0.1:6379> sadd userList wangwu

查看数据:smembers key

127.0.0.1:6379> smembers userList
1) "zhangsan"
2) "wangwu"
3) "lisi"

获取元素数量:scard key

127.0.0.1:6379> scard userList
(integer) 3
127.0.0.1:6379> 

移除集合元素:srem key value

127.0.0.1:6379> srem userList lisi
(integer) 1
127.0.0.1:6379> smembers userList
1) "zhangsan"
2) "wangwu"
127.0.0.1:6379> 

 

求集合的交集(intersection):sinter key1 key2 

127.0.0.1:6379> sadd list1 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd list2 1 2 5 6 
(integer) 4127.0.0.1:6379> SINTER list1 list2
1) "1"
2) "2"

求集合的并集:sunion key1 key2

127.0.0.1:6379> SUNION list1 list2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"

求集合的差集:sdiff key1 key2

127.0.0.1:6379> sdiff list1 list2
1) "3"
2) "4"
127.0.0.1:6379> 

 

5.ZSet 有序集合

ZSet,也称 sortedSet,在 Set 的基础上,加入了有序功能,在添加元素的时候,允许指定一个分数,它会按照这个分数排序。

添加数据:zadd key score value

127.0.0.1:6379> zadd manList 10 zhanggen
(integer) 1
127.0.0.1:6379> zadd manList 20 zhanggen1
(integer) 1
127.0.0.1:6379> zadd manList 30 zhanggen2
(integer) 1

查询数据:zrange key [开始索引 结束索引]

127.0.0.1:6379> zrange manList 0 -1
1) "zhanggen"
2) "zhanggen1"
3) "zhanggen2"

查询数据并根据 score 排序

127.0.0.1:6379> zrange manList 0 -1 withscores
1) "zhanggen"
2) "10"
3) "zhanggen1"
4) "20"
5) "zhanggen2"
6) "30"
127.0.0.1:6379> 

删除数据:zrem key value

127.0.0.1:6379> zrem manList zhanggen2
(integer) 1

 

6.通用命令

通用命令指的是不受数据类型限制的一批命令

1. 模糊查询键:keys 模糊匹配规则

127.0.0.1:6379> keys list*
1) "list1"
2) "list2"
3) "list"

2. 根据键判断记录是否存在:exists key

127.0.0.1:6379> exists a
(integer) 0
127.0.0.1:6379> exists list1
(integer) 1
127.0.0.1:6379> 

3. 根据键判断值类型:type key

127.0.0.1:6379> type list1
set
127.0.0.1:6379> 

4. 返回 key 的剩余生存时间:TTL key

返回 -2 表示当前 key 已经过期;

127.0.0.1:6379> setex name 5 wangge
OK
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2

5. 选择数据库: select 库索引 [从 0 开始]

127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]> setex name 3 zhangyu
OK

6. 清空当前数据库: flushdb

127.0.0.1:6379[3]> flushdb
OK127.0.0.1:6379[3]> keys *
(empty array)

7. 清空所有数据库: flushall 

127.0.0.1:6379[3]> flushall
OK
127.0.0.1:6379[3]> keys *
(empty array)
127.0.0.1:6379[3]> select 1
OK127.0.0.1:6379[1]> keys *
(empty array)
127.0.0.1:6379[1]> 

 

三、Java 操作 Redis

如何使用 Java 程序连接 Redis

1.Jedis

Redis 作为一款优秀的缓存服务器存在,大多数语言都提供了连接 Redis 的驱动包,在 Java 中,比较出名的是 Jedis。

1.1. 引入 Pom 依赖 

<dependencies>
        <!--加入 jedis 依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.3</version>
        </dependency>
        <!--加入单元测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

1.2. 代码测试

package com.zhanggen.test;

import org.junit.After;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Set;

public class JedisTest1 {
//1. 创建 Jedis 客户端
private Jedis jedis = new Jedis("192.168.56.18", 6379);

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testString() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.使用Jedis客户端操作String</span>
    jedis.setex("name", 6, "张根"<span style="color: rgba(0, 0, 0, 1)">);
    String name </span>= jedis.get("name"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(name);
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testList() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.使用Jedis客户端操作list</span>
    jedis.lpush("userList", "张弢", "张启樵", "张三丰", "张无忌"<span style="color: rgba(0, 0, 0, 1)">);
    List</span>&lt;String&gt; userList = jedis.lrange("userList", 0, -1<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (String user : userList) {
        System.out.println(user);
    }
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testHash() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.使用Jedis客户端操作hash</span>
    jedis.hset("user", "name", "张根"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.hset(</span>"user", "age", "18"<span style="color: rgba(0, 0, 0, 1)">);
    String name </span>= jedis.hget("user", "name"<span style="color: rgba(0, 0, 0, 1)">);
    String age </span>= jedis.hget("user", "age"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(name);
    System.out.println(age);
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testSet() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.使用Jedis客户端操作集合set</span>
    jedis.sadd("name", "Martin"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.sadd(</span>"name", "Jack"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.sadd(</span>"name", "Tom"<span style="color: rgba(0, 0, 0, 1)">);
    Set</span>&lt;String&gt; userList = jedis.smembers("name"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (String user : userList) {
        System.out.println(user);
    }
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testZset() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.使用Jedis客户端操作有序集合Zset</span>
    jedis.zadd("programingLanguages", 1, "C"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.zadd(</span>"programingLanguages", 2, "C++"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.zadd(</span>"programingLanguages", 3, "Java"<span style="color: rgba(0, 0, 0, 1)">);
    jedis.zadd(</span>"programingLanguages", 0, "Python"<span style="color: rgba(0, 0, 0, 1)">);
    Set</span>&lt;String&gt; programingLanguages = jedis.zrange("programingLanguages", 0, -1<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (String language : programingLanguages) {
        System.out.println(language);
    }

}


@After
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> colseRedis() {
    ;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">3.关闭客户端</span>

jedis.close();
System.out.println(
"关闭 Redis 成功");
}
}

 

2.SpringDataRedis

Spring 是用于开发企业级 Web 应用的框架,这个框架由很多子项目组成,之前我们学习了 Spring 框架中的 JDBC、MVC 和 Boot;

SpringData 也是 Spring 框架下的 1 个子项目,主要封装了持久层的解决方案;

SpringDataRedis 是 SpringData 子项目下 1 个子项目;

SpringDataRedis 对 Redis 底层开发包进行了高度封装,提供了一个高度封装的类:RedisTemplate,用于操作 Redis 各种数据类型。

  • ValueOperations:简单 K-V 操作

  • SetOperations: set 类型数据操作

  • ZSetOperations: zset 类型数据操作

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

  • ListOperations: 针对 list 类型的数据操作

 

2.1. 环境准备

2.1.1. 创建 SpringBoot 工程

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
    </parent>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-boot-starter-test<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">scope</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>test<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">scope</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>junit<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>junit<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-boot-starter-data-redis<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">build</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">plugins</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">plugin</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-boot-maven-plugin<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>2.4.5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">plugin</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">plugins</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">build</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
pom.xml

2.1.2.SpringBoot 配置文件

spring:
  redis:
    host: 192.168.56.18  #redis 服务器的 IP
    port: 6379
    database: 0 # 操作的是 0 号数据库
    jedis: #Redis 连接池配置
      pool:
        max-active: 8 #最大连接数
        max-wait: 1ms #连接池最大阻塞等待时间
        max-idle: 4 #连接池中的最大空闲连接
        min-idle: 0 #连接池中的最小空闲连接
application.yaml

2.1.3.创建主类

package com.zhanggen;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.
class, args);
}
}

RedisApplication.java

2.1.4. 提供配置类

package com.zhanggen.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

//Redis 配置类
//当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,
//但是默认的 key 序列化器为 JdkSerializationRedisSerializer,导致我们存到 Redis 中后的数据和原始数据有差别
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

@Bean
</span><span style="color: rgba(0, 0, 255, 1)">public</span> RedisTemplate&lt;Object, Object&gt;<span style="color: rgba(0, 0, 0, 1)"> redisTemplate(RedisConnectionFactory connectionFactory) {

    RedisTemplate</span>&lt;Object, Object&gt; redisTemplate = <span style="color: rgba(0, 0, 255, 1)">new</span> RedisTemplate&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">();

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置Key的序列化器  默认是JdkSerializationRedisSerializer</span>
    redisTemplate.setKeySerializer(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringRedisSerializer());
    redisTemplate.setHashKeySerializer(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringRedisSerializer());

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置value的序列化器   默认是JdkSerializationRedisSerializer
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">redisTemplate.setValueSerializer(new StringRedisSerializer());
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">redisTemplate.setHashValueSerializer(new StringRedisSerializer());

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">为了解决数字自增问题
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer&lt;Object&gt;(Object.class));</span>

redisTemplate.setConnectionFactory(connectionFactory);

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> redisTemplate;
}

}

RedisConfig.java

2.1.5. 提供测试类

package com.zhanggen.test;

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.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.concurrent.TimeUnit;

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringDataRedisTest {

@Autowired
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> RedisTemplate redisTemplate;


@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testString() {
    ValueOperations ops </span>=<span style="color: rgba(0, 0, 0, 1)"> redisTemplate.opsForValue();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">增加数据</span>
    ops.set("1001", "张三"<span style="color: rgba(0, 0, 0, 1)">);
    ops.set(</span>"1002", "李四"<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取</span>
    System.out.println(ops.get("1001"<span style="color: rgba(0, 0, 0, 1)">));

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置有效时间</span>
    ops.set("1003", "王五", 60<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果不存在,再新增</span>
    ops.setIfAbsent("1004", "赵六"<span style="color: rgba(0, 0, 0, 1)">);
    ops.setIfAbsent(</span>"1004", "钱八"<span style="color: rgba(0, 0, 0, 1)">);

// //自增 自减
// ops.set("age", 18);
// ops.increment("age", 3);
// ops.decrement("age", 2);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除</span>
    redisTemplate.delete("1001"<span style="color: rgba(0, 0, 0, 1)">);
}

}

SpringDataRedisTest.java

 

2.2. 操作字符串类型数据

  //测试字符串
    @Test
    public void testString() {
        ValueOperations ops = redisTemplate.opsForValue();
        //新增数据
        ops.set("name", "张根");
        //获取数据
        String name = (String) ops.get("name");
        System.out.println(name);
        //设置有效时间 6 秒
        ops.set("1003", "王五", 60, TimeUnit.SECONDS);
        //如果不存在再新增
        ops.setIfAbsent("1004", "赵六");
        //自增 / 自减
        ops.set("age", 18);
        ops.increment("age", 6);
        ops.decrement("age", 3);
        System.out.println(ops.get("age"));
        //删除
        redisTemplate.delete("name");}

 

2.3. 操作哈希类型数据

//测试 Hash
    @Test
    public void testHash() {
        HashOperations ops = redisTemplate.opsForHash();
        //1. 新增数据
        ops.put("user", "name", "张根");
        ops.put("user", "age", "18");
        ops.put("user", "sex", "Man");
        //获取 user 的 name 属性
        Object userName = ops.get("user", "name");
        System.out.println(userName);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取所有的key</span>
    Set keys = ops.keys("user"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Object key : keys) {
        System.out.println(key);
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取所有的values</span>
    List values = ops.values("user"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Object value : values) {
        System.out.println(value);
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除某1属性</span>
    ops.delete("user", "name"<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除整个hash</span>
    ops.delete("user"<span style="color: rgba(0, 0, 0, 1)">);

}</span></pre>

 

2.4. 操作列表类型数据

//测试 list
    @Test
    public void testList() {
        ListOperations ops = redisTemplate.opsForList();
        ops.leftPush("userList", "张根");
        ops.leftPushAll("userList", "b", "C", "D");
        //获取 list 的长度
        System.out.println(ops.size("userList"));
        //遍历
        List userList = ops.range("userList", 0, -1);
        for (Object o : userList) {System.out.println(o);
        }
        //删除
        ops.rightPop("userList");}

 

2.5. 操作无序集合类型数据

 //测试 set
    @Test
    public void testSet() {
        SetOperations ops = redisTemplate.opsForSet();
        //添加
        ops.add("501", "A", "b", "c");
        //遍历查询
        Set members = ops.members("501");
        for (Object member : members) {System.out.println(member);
        }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">移除集合元素</span>
    ops.remove("501", "A", "b"<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取set长度</span>
    Long size = ops.size("501"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(size);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">求2个集合的交集</span>
    ops.add("502", "A", "B", "c"<span style="color: rgba(0, 0, 0, 1)">);
    Set intersect </span>= ops.intersect("501", "502"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(intersect);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">求2个集合的差集</span>
    Set difference = ops.difference("501", "502"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(difference);


}</span></pre>

 

2.6.操作有序集合类型数据

   //测试有序集合 Zset
    @Test
    public void testZset() {
        ZSetOperations ops = redisTemplate.opsForZSet();
        //添加
        ops.add("5001", "Tom", 10);
        ops.add("5001", "Jack", 20);
        ops.add("5001", "Albert", 30);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">遍历查询</span>
    Set userSet = ops.range("5001", 0, -1<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Object user : userSet) {
        System.out.println(user);
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">修改有序集合中的元素的分数 +16分</span>
    ops.incrementScore("5001", "Jack", 16<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除有序集合中的元素</span>
    ops.remove("5001", "Albert"<span style="color: rgba(0, 0, 0, 1)">);

}</span></pre>

 

2.7.通用操作

 //测试通用 API
    @Test
    public void testGenericOperation() {
        //模糊查询 redis 数据库中所有 key
        Set keys = redisTemplate.keys("*");
        for (Object key : keys) {System.out.println(key);
        }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断key是否存在</span>
    Boolean isExist = redisTemplate.hasKey("5001"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(isExist);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断key的类型</span>
    DataType type = redisTemplate.type("5001"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(type.name());

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断key剩余存活时间</span>
    Long expire = redisTemplate.getExpire("5001"<span style="color: rgba(0, 0, 0, 1)">);
    System.out.println(expire);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除key</span>
    redisTemplate.delete("5001"<span style="color: rgba(0, 0, 0, 1)">);
    
}</span></pre>

 

 

 

 

 

 

 

 

参考