文章目录
- Redis基础
- 课程内容
- 1. 前言
- 1.1 什么是Redis
- 1.2 使用Redis能做什么
- 2. Redis入门
- 2.1 Redis简介
- 2.2 Redis下载与安装
- 2.2.1 Redis下载
- 2.2.2 Redis安装
- 2.3 Redis服务启动与停止
- 2.4 Redis配置文件
- 3. Redis数据类型
- 3.1 介绍
- 3.2 Redis 5种常用数据类型
- 4. Redis常用命令
- 4.1 字符串string操作命令
- 4.2 哈希hash操作命令
- 4.3 列表list操作命令
- 4.4 集合set操作命令
- 4.5 有序集合sorted set操作命令
- 4.6 通用命令
- 5. 在Java中操作Redis
- 5.0 初始java环境准备
- 5.1 介绍
- 5.2 Jedis
- 5.3 Spring Data Redis
- 5.3.1 介绍
- 5.3.2 使用方式
- 5.3.2.1 环境搭建
- 5.3.2.2 操作字符串类型数据
- 5.3.2.3 操作哈希类型数据
- 5.3.2.4 操作列表类型数据
- 5.3.2.5 操作集合类型数据
- 5.3.2.6 操作有序集合类型数据
- 5.3.2.7 通用操作
Redis基础
课程内容
- Redis入门
- Redis数据类型
- Redis常用命令
- 在Java中操作Redis
1. 前言
1.1 什么是Redis
Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件,它是「Remote Dictionary Service」的首字母缩写,也就是「远程字典服务」。
- 基于内存存储,读写性能高
- 适合存储热点数据(热点商品、资讯、新闻)
- 企业应用广泛
1.2 使用Redis能做什么
- 数据缓存
- 消息队列
- 注册中心
- 发布订阅
2. Redis入门
2.1 Redis简介
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. 翻译为:Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。
官网:https://redis.io
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。它存储的value类型比较丰富,也被称为结构化的NoSql数据库。
NoSql(Not Only SQL),不仅仅是SQL,泛指非关系型数据库。NoSql数据库并不是要取代关系型数据库,而是关系型数据库的补充。
关系型数据库(RDBMS):
- Mysql
- Oracle
- DB2
- SQLServer
非关系型数据库(NoSql):
- Redis
- Mongo db
- MemCached
2.2 Redis下载与安装
2.2.1 Redis下载
Redis安装包分为windows版和Linux版:
- Windows版下载地址:https://github.com/microsoftarchive/redis/releases
- Linux版下载地址: https://download.redis.io/releases/
linux 我们下载4.0.0
下载后得到下面安装包:
2.2.2 Redis安装
1)在Linux中安装Redis
在Linux系统安装Redis步骤:
- 将Redis安装包上传到Linux
- 解压安装包,命令:tar -zxvf redis-4.0.0.tar.gz -C /usr/local
- 安装Redis的依赖环境gcc,命令:yum install gcc-c++
- 进入/usr/local/redis-4.0.0,进行编译,命令:make
- 进入redis的src目录进行安装,命令:make install
安装后重点文件说明:
/usr/local/redis-4.0.0/src/redis-server:Redis服务启动脚本
/usr/local/redis-4.0.0/src/redis-cli:Redis客户端脚本
/usr/local/redis-4.0.0/redis.conf:Redis配置文件
2)在Windows中安装Redis
Redis的Windows版属于绿色软件,直接解压即可使用,解压后目录结构如下:
2.3 Redis服务启动与停止
1)Linux系统中启动和停止Redis
执行Redis服务启动脚本文件redis-server:
redis服务端启动:
通过启动日志可以看到,Redis默认端口号为6379。
Ctrl + C停止Redis服务
通过redis-cli可以连接到本地的Redis服务,默认情况下不需要认证即可连接成功。
redis客户端启动: (再开一个linux终端哦)
退出客户端可以输入exit或者quit命令。
- 修改linux端服务后台运行,不霸屏
肯定是修改配置文件喽
vim /usr/local/redis-4.0.0/redis.conf
查找: /dae
修改: daemonize no => daemonize yes
重新启动(得加上配置文件作为参数): src/redis-server ./redis.conf
2)Windows系统中启动和停止Redis
Windows系统中启动Redis,直接双击redis-server.exe即可启动Redis服务,redis服务默认端口号为6379
Ctrl + C停止Redis服务
双击redis-cli.exe即可启动Redis客户端,默认连接的是本地的Redis服务,而且不需要认证即可连接成功。
退出客户端可以输入exit或者quit命令。
2.4 Redis配置文件
前面我们已经启动了Redis服务,默认情况下Redis启动后是在前台运行,而且客户端不需要密码就可以连接到Redis服务。如果我们希望Redis服务启动后是在后台运行,同时希望客户端认证通过后才能连接到Redis服务,应该如果做呢?
此时就需要修改Redis的配置文件:
- Linux系统中Redis配置文件:REDIS_HOME/redis.conf
- Windows系统中Redis配置文件:REDIS_HOME/redis.windows.conf
通过修改Redis配置文件可以进行如下配置:
1) 设置Redis服务后台运行
将配置文件(redis-4.0.0/redis.conf)中的daemonize配置项改为yes,默认值为no。
注意:Windows版的Redis不支持后台运行。
2) 设置Redis服务密码
将配置文件中的 # requirepass foobared 配置项取消注释,默认为注释状态。foobared为密码,可以根据情况自己指定。
密码登录方式1:
./redis-cli -h localhost -p 6379
auth 123456
密码登录方式2:
./redis-cli -h localhost -p 6379 -a 123456
3) 设置允许客户端远程连接Redis服务
Redis服务默认只能客户端本地连接,不允许客户端远程连接。将配置文件中的 bind 127.0.0.1 配置项注释掉。
注意防火墙的存在,还得打开6379端口
# 打开6379 端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
# 立即生效
firewall-cmd --reload
# 查看开放端口
firewall-cmd --zone=public --list-ports
解释说明:
Redis配置文件中 # 表示注释
Redis配置文件中的配置项前面不能有空格,需要顶格写
daemonize:用来指定redis是否要用守护线程的方式启动,设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行
requirepass:设置Redis的连接密码
bind:如果指定了bind,则说明只允许来自指定网卡的Redis请求。如果没有指定,就说明可以接受来自任意一个网卡的Redis请求。
注意:修改配置文件后需要重启Redis服务配置才能生效,并且启动Redis服务时需要显示的指定配置文件:
1)Linux中启动Redis服务
# 进入Redis安装目录
cd /usr/local/redis-4.0.0
# 启动Redis服务,指定使用的配置文件
./src/redis-server ./redis.conf
2)Windows中启动Redis服务
先将windows端的配置文件也对应地修改了,windows改后2处即可
由于Redis配置文件中开启了认证校验,即客户端连接时需要提供密码,此时客户端连接方式变为:
解释说明:
-h:指定连接的Redis服务的ip地址
-p:指定连接的Redis服务的端口号
-a:指定连接的Redis服务的密码
3. Redis数据类型
3.1 介绍
Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:
- 字符串 string
- 哈希 hash
- 列表 list
- 集合 set
- 有序集合 sorted set / zset
3.2 Redis 5种常用数据类型
解释说明:
字符串(string):普通字符串,常用
哈希(hash):适合存储对象
列表(list):按照插入顺序排序,可以有重复元素
集合(set):无序集合,没有重复元素
有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素
4. Redis常用命令
4.1 字符串string操作命令
Redis 中字符串类型常用命令:
- SET key value 设置指定key的值
- GET key 获取指定key的值
- SETEX key seconds value 设置指定key的值,并将 key 的过期时间设为 seconds 秒
- SETNX key value 只有在 key 不存在时设置 key 的值
更多命令可以参考Redis中文网:https://www.redis.net.cn
# 设置值 name="xiaoming"
set name xiaoming
# 返回 "xiaoming"
get name
# 返回 nil
get age
set age 18
# 返回 "18"
get age
# 重新设置 age = "30"
set age 30
# 再get 就返回 "30" 了
get age
# 设置 city="beijing" 但是该变量只能存活10s (很适用于验证码的失效处理)
setex city 10 beijing
# 10s内 返回 “beijing”
get city
# 10s后 返回 nil
get city
# 返回1 表示设置成功
setnx id 123
# setnx 再次设置id的值 id已经有值了 设置不成功 返回0
setnx id 456
# 肯定返回123啦
get id
4.2 哈希hash操作命令
Redis hash 是一个string类型的 field 和 value 的映射表,hash特别适合用于存储对象,常用命令:
- HSET key field value 将哈希表 key 中的字段 field 的值设为 value
- HGET key field 获取存储在哈希表中指定字段的值
- HDEL key field 删除存储在哈希表中的指定字段
- HKEYS key 获取哈希表中所有字段
- HVALS key 获取哈希表中所有值
- HGETALL key 获取在哈希表中指定 key 的所有字段和值
# key=001 实际中可以是id为001的用户
# 设置001用户的信息
hset 001 name xiaoming
# 继续设置001用户的信息
hset 001 age 18
# 获取001用户的信息:"xiaoming"
hget 001 name
# 获取001用户的信息 "18"
hget 001 age
# 获取所有字段: 1) "name" 2) "age"
hkeys 001
# 删除用户001的age属性
hdel 001 age
# 此时再获取age自然返回: nil 了
hget 001 age
# 也只有: 1) "name" 了
hkeys 001
hset 001 age 20
# 获取key=001 中所有 keys: 1) "name" 2) "age"
hkeys 001
# 获取key=001 中所有 values: 1) "xiaoming" 2) "20"
hvals 001
# 获取key=001 中所有 key和value: 1) "name" 2) "xiaoming" 3) "age" 4) "20"
hgetall 001
# 获取压根儿就不存在的,肯定返回 nil 了
hget 002 abc
4.3 列表list操作命令
Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令:
- LPUSH key value1 [value2] 将一个或多个值插入到列表头部
- LRANGE key start stop 获取列表指定范围内的元素
- RPOP key 移除并获取列表最后一个元素
- LLEN key 获取列表长度
- BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止
# ctrl + l 也可以清屏
# l:左边 左边一次性插入 “a b c”
lpush mylist a b c
# 查询指定范围的值 起点0 终点-1表示就是list末尾: 1) "c" 2) "b" 3) "a"
lrange mylist 0 -1
# 再插入一个值: "whu"
lpush mylist whu
# 查看所有元素: 1) "whu" 2) "c" 3) "b" 4) "a" 【有点类似栈(双端队列更好)啊】
lrange mylist 0 -1
# 列表里可以有重复元素
lpush mylist a
# 1) "a" 2) "whu" 3) "c" 4) "b" 5) "a"
lrange mylist 0 -1
# 弹出右边第一个元素 (也就是第一个入队的元素 看成队列就是队头) 返回 第5个"a"
rpop mylist
# 第5个a没有了: 1) "a" 2) "whu" 3) "c" 4) "b"
lrange mylist 0 -1
# 肯定返回b了
rpop mylist
# 队头的b又没有了: 1) "a" 2) "whu" 3) "c"
lrange mylist 0 -1
# list的长度: 3
llen mylist
# 弹出mylist最后一个元素 c
brpop mylist 10
# 弹出mylist最后一个元素 whu
brpop mylist 10
# 弹出mylist最后一个元素 a
brpop mylist 10
# 队列里没有元素了: (empty list or set)
lrange mylist 0 -1
# mulist没有元素了,被阻塞, 超时时间我们设置为10s, 10s后还是没有找到列表元素弹出,就返回 nil 了
brpop mylist 10
4.4 集合set操作命令
Redis set 是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:
- SADD key member1 [member2] 向集合添加一个或多个成员
- SMEMBERS key 返回集合中的所有成员
- SCARD key 获取集合的成员数
- SINTER key1 [key2] 返回给定所有集合的交集
- SUNION key1 [key2] 返回所有给定集合的并集
- SDIFF key1 [key2] 返回给定所有集合的差集
- SREM key member1 [member2] 移除集合中一个或多个成员
# 向集合中加入4个元素
sadd myset a b c d
# 查看集合元素: 1) "d" 2) "c" 3) "b" 4) "a" 集合肯定是无序的啦
smembers myset
# 继续加入两个重复的元素,返回0, 肯定加入失败, 因为集合元素 不能重复
sadd myset a b
# 查看集合元素, 还是那四个: 1) "c" 2) "b" 3) "a" 4) "d" (当然,他是无序的)
smembers myset
# 获取集合成员数量: 4
scard myset
# 再创建一个集合,以便进行集合运算
sadd myset2 a b x y
# 1) "y" 2) "x" 3) "b" 4) "a"
smembers myset2
# 求两个集合的交集: 1) "b" 2) "a"
sinter myset myset2
# 求2个集合的并集: 1) "a" 2) "d" 3) "c" 4) "b" 5) "y" 6) "x"
sunion myset myset2
# 两个集合差集
# myset - myset2 = {a,b,c,d}-{a,b,x,y}={c,d}
sdiff myset myset2
# myset2 - myset = {a,b,x,y}-{a,b,c,d}={x,y}
sdiff myset2 myset
# 移除集合中的元素: a b c 【本来myset中是a b c d 现在移除了a b c】
srem myset a b c
# 只剩下 d 了
smembers myset
4.5 有序集合sorted set操作命令
Redis sorted set 有序集合是 string 类型元素的集合,且不允许重复的成员。每个元素都会关联一个double类型的分数(score) 。redis正是通过分数来为集合中的成员进行从小到大排序。有序集合的成员是唯一的,但分数却可以重复。
常用命令:
- ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的 分数
- ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
- ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
- ZREM key member [member …] 移除有序集合中的一个或多个成员
# 新建有序集合myset3 向里面添加两个元素 a 和 b 分数分别是10.0 和 9.0 也就是b会排在前面
zadd myset3 10.0 a 9.0 b
# 查看有序集合所有元素: b a 【b果然排在前面】
zrange myset3 0 -1
# 再插入一个元素c, 分数9.9 界于二者之间
zadd myset3 9.9 c
# 再查看所有,确实根据分值排序的: 1) "b" 2) "c" 3) "a"
zrange myset3 0 -1
# 查看所有,元素和分数一起展示: 1) "b" 2) "9" 3) "c" 4) "9.9000000000000004" 5) "a" 6) "10"
zrange myset3 0 -1 withscores
# b的分值加20,返回: 29 【20+9=29】
zincrby myset3 20 b
# b分值现在最大,就跑到最后面去了: 1) "c" 2) "a" 3) "b"
zrange myset3 0 -1
# 删除有序集合myset3里的元素b
zrem myset3 b
# 再查看所有,b没有了: 1) "c" 2) "a"
zrange myset3 0 -1
4.6 通用命令
Redis中的通用命令,主要是针对key进行操作的相关命令:
- KEYS pattern 查找所有符合给定模式( pattern)的 key
- EXISTS key 检查给定 key 是否存在
- TYPE key 返回 key 所储存的值的类型
- TTL key 返回给定 key 的剩余生存时间(TTL, time to live),以秒为单位
- DEL key 该命令用于在 key 存在时删除 key
SETEX key seconds value 设置指定key的值,并将 key 的过期时间设为 seconds 秒
回顾一下4.1 字符串string操作命令
, 超时时间设置在中间
# 列出来 所有的 key: "id" "name" "age" "myset" "001" "myset2" "myset3"
keys *
# 查看 name 这个key 是否存在 返回:1 表示存在
exists name
# 查看 sex 这个key 是否存在 返回:0 表示不存在
exists sex
# 查看 name(这个key对应值) 的类型: string
type name
# set 普通set集合
type myset
# zset 有序集合
type myset3
# hash 类型
type 001
# 查看指定key的存活时间 -1 表示永久
# 查看name的存活时间: -1 永久存活
ttl name
# 新建 school=”whu“ 过期时间为100s
setex school 100 whu
# 等一会儿再去执行, 返回: 46 【还有46s 该key就失效了】
ttl school
# 过期后再查看,返回: -2 就是表示已经过期了
ttl school
# del key 删除指定 key
del id
# 发现少了 "id"
keys *
# 一次性删除多个key
del name age 001
# 果然就剩下3了: "myset" "myset2" "myset3"
keys *
5. 在Java中操作Redis
5.0 初始java环境准备
删除多余的webapp 然后创建cn.whu.test.JedisTest,最终如下
其中pom.xml 要修改为如下形式,先提前贴出来吧
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.whu</groupId>
<artifactId>jedis_demo</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- junit测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- jedis依赖包 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
</project>
5.1 介绍
前面我们讲解了Redis的常用命令,这些命令是我们操作Redis的基础,那么我们在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。
Redis 的 Java 客户端很多,官方推荐的有三种:
- Jedis
- Lettuce
- Redisson
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。
5.2 Jedis
Jedis 是 Redis 的 Java 版本的客户端实现。
maven坐标:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
使用 Jedis 操作 Redis 的步骤:
- 获取连接
- 执行操作
- 关闭连接
示例代码:
基本上有哪些redis命令,就有哪些对应的java方法
package cn.whu.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import java.util.Set;
/**
* 使用jedis操作Redis
*/
public class JedisTest {
@Test
public void testRedis(){
//1. 获取连接
Jedis jedis = new Jedis("localhost", 6379);//就类似jdbc里的connection
//2. 执行具体操作
// 设置值
jedis.set("name","xiaoming");
jedis.set("username","daming");
// 获取值
String username = jedis.get("username");
System.out.println(username);//daming
// 删除key
jedis.del("username");
System.out.println(jedis.get("username"));//null
// 2.2 设置 hash 类型的值
jedis.hset("myhash","age","18");
String age = jedis.hget("myhash","age");
System.out.println(age);//18
// 还有一系列操作 之前学过命令 这里就肯定会写方法
// eg: 2.3 zset 操作
jedis.zadd("myzset",1.0,"hza");
jedis.zadd("myzset",3.0,"yth");
jedis.zadd("myzset",2.0,"lml");
Set<String> myzset = jedis.zrange("myzset", 0, -1);
System.out.println(myzset);//[hza, lml, yth]
Set<Tuple> tuples = jedis.zrangeWithScores("myzset", 0l, -1l);
System.out.println(tuples);//[[[104, 122, 97],1.0], [[108, 109, 108],2.0], [[121, 116, 104],3.0]]
for (Tuple tuple : tuples) {
System.out.println(tuple.getElement()+"\t"+tuple.getScore());
//hza 1.0
//lml 2.0
//yth 3.0
}
// 2.4 通用操作
// keys *
Set<String> keys = jedis.keys("*");
System.out.println(keys);//[name, myhash, myset3, myset2, myzset, myset]
//3. 关闭连接
jedis.close();
}
}
注意执行前先启动redis服务,windows下直接双击
redis-server.exe
即可
命令行启动客户端,也能访问到java代码存入的key-value
5.3 Spring Data Redis
5.3.1 介绍
Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。
网址:https://spring.io/projects/spring-data-redis
maven坐标:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.4.8</version>
</dependency>
Spring Boot提供了对应的Starter,maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Spring Data Redis中提供了一个高度封装的类:RedisTemplate,针对 Jedis 客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
- ValueOperations:简单K-V操作
- SetOperations:set类型数据操作
- ZSetOperations:zset类型数据操作
- HashOperations:针对hash类型的数据操作
- ListOperations:针对list类型的数据操作
5.3.2 使用方式
5.3.2.1 环境搭建
接下来再次手工搭建一下boot工程(好处,连不上spring.io也可以搭建boot工程)
第0步:创建普通maven工程,修改目录结构
修改目录结构如下,并新建4个文件(下图已经框出)
接下来再一步步修改文件内容
第一步:配置pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<groupId>cn.whu</groupId>
<artifactId>springdataredis_demo</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.5</version>
</plugin>
</plugins>
</build>
</project>
第二步:编写启动类 App
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
}
}
第三步:配置application.yml
spring:
application:
name: springdataredis_demo
#Redis相关配置
redis:
host: localhost
port: 6379
#password: 123456
database: 0 #操作的是0号数据库 (redis服务启动,默认提供了16个数据库)
jedis:
#Redis连接池配置
pool:
max-active: 8 #最大连接数
max-wait: 1ms #连接池最大阻塞等待时间
max-idle: 4 #连接池中的最大空闲连接
min-idle: 0 #连接池中的最小空闲连接
解释说明:
spring.redis.database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。
可以通过修改Redis配置文件来指定数据库的数量。
查看配置文件: /Redis-x64-3.2.100/redis.windows.conf
第四步:提供配置类 cn.whu.config.RedisConfig
package com.itheima.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.StringRedisSerializer;
/**
* Redis配置类
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
//默认的Key序列化器为:JdkSerializationRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
解释说明:
当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别
不配置的话,显示会很奇怪,明明 set city beijing
但是key却显示 "\xac\xed\x00\x05t\x00\x04city"
配置好后能获取但是value值还是有问题
但是这里并不会去配置value了,因为java代码get值时会自动反序列化,从而自动解决这个问题
第五步:提供测试类: cn.whu.test.SpringDataRedisTest
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringDataRedisTest {
// 注入RedisTemplate 一个高度封装的类 用来方便地操作redis
// 只要yml配置文件写了redis配置 spring就自动装配(bean中没有时帮你new) 这里就可以注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
}
5.3.2.2 操作字符串类型数据
/**
* 操作String类型数据
* @throws InterruptedException
*/
@Test
public void testString() throws InterruptedException {
// 获取string类型操作器
ValueOperations vops = redisTemplate.opsForValue();
// 设置普通 key-value 类型
vops.set("city","beijing");
vops.set("city123","beijing123");
// 根据key获取值
String city123 = (String) vops.get("city123");
System.out.println(city123);
// 设置过期时间 (验证码1234 过期时间1 单位s)
vops.set("code","1234",1l, TimeUnit.SECONDS);
String code = (String) vops.get("code");
System.out.println(code); // "1234"
Thread.sleep(1*1000);//休息1s 等待过期
code = (String) vops.get("code");
System.out.println(code); // null
// 如果不存在才设置
System.out.println(vops.setIfAbsent("city123","whu"));// false 表示设置失败
System.out.println(vops.setIfAbsent("addr","whu"));// true 表示设置成功
System.out.println(vops.get("city123"));// beijing123 已经存在 设置失败 还是原来的值
System.out.println(vops.get("addr"));// whu 原来没有 设置成功
}
5.3.2.3 操作哈希类型数据
/**
* 操作Hash类型数据
*/
@Test
public void testHash(){
// 获取Hash操作对象
HashOperations hops = redisTemplate.opsForHash();
// 存值: 设置hash类型的值 (模拟存储id=002的对象 给这个对象设置了3个属性)
hops.put("002","name","zhangsan");
hops.put("002","age","20");
hops.put("002","address","guangzhou1");
// 取值:
String name = (String) hops.get("002", "name");
System.out.println(name); // zhangsan
// 获得hash结构中所有字段
Set keys = hops.keys("002"); // 获取key=002的所有 hash类型的key
System.out.println(keys); // [name, age, address]
// 获取hash结构中所有的值
List values = hops.values("002");// 获取key=002的hash类型, 所有的value
System.out.println(values);// [zhangsan, 20, guangzhou1]
}
5.3.2.4 操作列表类型数据
/**
* 操作List类型的数据
*/
@Test
public void testList(){
// 获取list类型操作对象
ListOperations lops = redisTemplate.opsForList();
redisTemplate.delete("mylist");//提前有就先删除 以便重复访问
// 存值
lops.leftPush("mylist","a");//一次存一个值
lops.leftPushAll("mylist","b","c","d");//一次存多个值
// 取值
List mylist = lops.range("mylist", 0, -1);
System.out.println(mylist); // [d, c, b, a] 按照插入顺序排序 (看成从左往右插入的队列即可)
// 获得列表长度
int size = lops.size("mylist").intValue();
// 出队列 (想造队列 得从右边出啦)
for (int i = 0; i < size; i++) {
String element = (String) lops.rightPop("mylist");
System.out.print(element+" ");
}
System.out.println();
}
5.3.2.5 操作集合类型数据
/**
* 操作set类型的数据
*/
@Test
public void testSet(){
// 获取set类型操作对象
SetOperations sops = redisTemplate.opsForSet();
redisTemplate.delete("myset");
// 存值
sops.add("myset","a","b","c","d","a","b");//集合不能有重复 所有 a b 只能存一份
// 长度
Long size = sops.size("myset");
System.out.println(size);//4
// 取值
Set<String> myset = sops.members("myset");//set无需 自然无需指定获取值的下标范围
System.out.println(myset); // [d, a, c, b] 无序输出
// 删除成员
sops.remove("myset","a","b");
System.out.println(sops.members("myset"));//[d, c] a,b被删除了呀
}
5.3.2.6 操作有序集合类型数据
/**
* 操作ZSet类型的数据
* ZSet 是有序集合,不允许重复,通过分数来排序
*/
@Test
public void testZSet() {
// 获取set类型操作对象
ZSetOperations zsops = redisTemplate.opsForZSet();
redisTemplate.delete("myzset");
// 存值
zsops.add("myzset", "a", 1.0); // 注意value-score 的顺序(相对于redis命令)改了下
zsops.add("myzset", "b", 2.0);
zsops.add("myzset", "c", 3.0);
zsops.add("myzset", "a", 4.0); // 验证是否不能有重复 【会覆盖之前的a】
// 取值
Set<String> myzset = zsops.range("myzset", 0, -1);
System.out.println(myzset);
// 取值+取score
Set<ZSetOperations.TypedTuple> zset = zsops.rangeWithScores("myzset", 0, -1);
for (ZSetOperations.TypedTuple t : zset) {
System.out.println(t.getValue() + "\t" + t.getScore());
//b 2.0
//c 3.0
//a 4.0 // 虽然不能插入重复的a 但是score却被更新了
}
// 修改分数
zsops.incrementScore("myzset", "b", 20.0);//给"b"+20分
System.out.println(zsops.range("myzset", 0, -1));//[c, a, b] b现在最大 排最后了
// 删除成员
zsops.remove("myzset", "a", "b");
System.out.println(zsops.range("myzset", 0, -1));//[c] a、b被删了 只剩下c了
}
5.3.2.7 通用操作
/**
* 通用操作: 针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){
// 获取redis中所有的key
Set<String> keys = redisTemplate.keys("*");
System.out.println(keys);
// [myzset, myset2, city, addr, myset3, �� t city, city123, name, myset, 002, myhash]
// 判断某个key是否存在
Boolean myzset = redisTemplate.hasKey("myzset");
System.out.println(myzset);//true
Boolean abc = redisTemplate.hasKey("abc");
System.out.println(abc);//false
// 重命名key
redisTemplate.opsForValue().set("city","anhui");// 先设置一个key把 方便重复执行
// 重命名
redisTemplate.rename("city","city2");
System.out.println(redisTemplate.hasKey("city"));//false
System.out.println(redisTemplate.hasKey("city2"));//true
// 删除指定key
redisTemplate.delete("city2");
System.out.println(redisTemplate.hasKey("city2"));//false
// 获取指定key对应的value的数据类型
DataType dataType = redisTemplate.type("myset");
System.out.println(dataType);//SET
System.out.println(dataType.name());//SET
}