Centos7上安装Reids&Redis的基本使用&Java操作Redis

  • 安装Redis
  • 启动Redis
  • 默认启动Redis
  • 指定配置文件启动
  • 设置Redis开机自启
  • Redis客户端
  • Redis命令行客户端
  • 图形化桌面客户端
  • 连接Redis可能会出现的问题
  • Redis的常用命令
  • 操作通用命令
  • 查看Redis的操作命令的类型
  • 使用常用的通用命令
  • 操作String的常用命令
  • 操作Key的层级结构的常用命令
  • 操作Hash的常用命令
  • 操作List的常用命令
  • 操作Set的常用命令
  • 操作SortedSet的常用命令
  • Redis的Java客户端
  • Jedis
  • Jedis的连接池
  • SpringDataRedis
  • 解决向Redis中存储数据的乱码问题
  • 使用RedisTemplate自定义序列化的方式
  • 使用StringRedisTemplate方式的序列化
  • RedisTemplate与StringRedisTemplate的不同点
  • Hash类型数据的操作
  • List类型数据的操作
  • Set类型数据的操作
  • SortedSet类型数据的操作


安装Redis

首先打开虚拟机的终端。

centos redis 查询list长度 centos7查看redis状态_spring boot

输入命令 ip addr ,查看此时的IP地址。

centos redis 查询list长度 centos7查看redis状态_Redis_02

在输入下面命令

yum install -y gcc tcl

出现下述页面即代表成功。

centos redis 查询list长度 centos7查看redis状态_redis_03

下面将会使用 Xftp 软件将 redis的安装包上传到虚拟机。

打开Xfpt软件。点击新建,并且输入名称和主机,然后点击确定

centos redis 查询list长度 centos7查看redis状态_常用命令_04

下面选择上图中设置的名称,然后点击连接。

centos redis 查询list长度 centos7查看redis状态_redis_05

点击接受并保存。

centos redis 查询list长度 centos7查看redis状态_spring boot_06

然后输入你此时虚拟机上登录的用户名和密码即代表连接成功。

然后在Xfpt软件的右上端找到虚拟机上要安装redis的位置,这里安装路径为 /url/local/src,然后将redis的安装包拖拽到右侧即可。

注意 : 这里选择 /url/local/src,因为这里面主要存放一些第三方的源代码

centos redis 查询list长度 centos7查看redis状态_java_07

然后在虚拟机的终端上输入以下命令。

cd /usr/local/src/

进入到 /usr/local/src/ 目录后,然后输入以下命令开始解压redis的安装包。

tar -zxvf redis-6.2.6.tar.gz

centos redis 查询list长度 centos7查看redis状态_常用命令_08

此时输入 ls 命令可以看到redis已经解压成功了

centos redis 查询list长度 centos7查看redis状态_Redis_09

然后进入redis的安装目录

cd redis-6.2.6

然后输入开始编译命令

make && make install

centos redis 查询list长度 centos7查看redis状态_spring boot_10

等待安装,成功后就会出现如下显示

centos redis 查询list长度 centos7查看redis状态_redis_11

注意
Redis的默认安装路径是在 /usr/local/bin 的目录下。该目录已经默认配置到环境变量,因此可以在任意目录下运行这些命令

redis-cli:是redis提供的命令行客户端
redis-server:是redis的服务端启动脚本
redis-sentinel:是redis的哨兵启动脚本

centos redis 查询list长度 centos7查看redis状态_redis_12

启动Redis

默认启动Redis

在任意目录下输入以下命令即可启动Redis。

redis-server

下面图片即代表启动成功。

centos redis 查询list长度 centos7查看redis状态_常用命令_13

注意:这种方式启动属于前台启动,会阻塞整个会话窗口,如果窗口关闭或者按下 Ctrl + C,则代表着Redis停止。如果想要使用这种方式,则必须在打开一个终端使用

指定配置文件启动

如果要让Redis以后台方式启动,则必须修改Redis配置文件,就在我们之前解压的Redis安装包下 (/usr/local/src/redis-6.2.6),名字叫redis.conf

centos redis 查询list长度 centos7查看redis状态_常用命令_14

我们需要使用下述命令将 redis.conf 文件备份一份。以防止文件内容无法恢复。

cp redis.conf redis.conf.bck

centos redis 查询list长度 centos7查看redis状态_redis_15

通过下述命令修改 redis.conf 文件的配置

vim redis.conf

redis.conf文件修改的一些配置,注意:修改完成后一定要保存。这里必须要修改 bind 0.0.0.0 与 daemonize yes,其他的看自己选择。

# 允许访问的地址,默认是127.0.0.1,即就是只能在本地访问。
# 如果修改为 0.0.0.0 ,则可以在任意IP访问,生产环境不要设置为0.0.0.0。
bind 0.0.0.0

# 守护线程,修改为yes后即可在后台允许。
daemonize yes

# 设置密码,设置后访问Redis必须输入密码。
requirepass 123456

# 监听的端口。
port 6379

# 工作目录,默认是当前目录,也就是允许redis-server时的命令、日志、持久化等文件会保存在这个目录。
dir .

# 数据库数量,设置1,代表只使用1个库,默认有16个库,编号0~15
databases 1

# 设置redis能够使用的最大内存
maxmemory 512mb

# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log"

# 设置保护模式 -- 需要密码登录
protected-mode yes

使用指定配置文件启动Reids

# 进入到Redis的安装目录
cd /usr/local/src/redis-6.2.6

# 启动Redis
redis-server redis.conf

此时发现并没有显示什么,那么使用下述命令判断是否在后台启动了Redis。

ps -ef | grep redis

如果出现了下面的图片所出现的,即意味着后台启动成功。

centos redis 查询list长度 centos7查看redis状态_Redis_16

设置Redis开机自启

①:创建一个系统服务文件。

vi /etc/systemd/system/redis.service

②:给其文件添加内容。

[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf # 注意redis的安装路径
PrivateTmp=true

[Install]
WantedBy=multi-user.target

③:重载系统服务

systemctl daemon-reload

④:启动Redis

systemctl start redis

⑤:停止、重启Redis的命令

# 重启
systemctl restart redis
# 停止
systemctl stop redis

⑥:查看Redis的状态

# 查看状态
systemctl status redis

Redis客户端

Redis命令行客户端

Redis安装成功后会自带一个命令行客户端 :redis-cli

使用方式:

redis-cli [options] [commonds]

常见的options有:
-h 127.0.0.1 : 指定要连接的redis节点的IP地址,默认是127.0.0.1。
-p 6379 :指定要连接的redis节点的端口,默认是6379。
-a 123456:指定redis的访问密码。

常见的commands就是Redis的操作命令,如:
ping:与redis服务端做心跳测试,服务端正常会返回 PONG。

注意:这里如果不指定commonds的话,就会进入 redis-cli的交互控制台。也就是说我们想要操作Redis,必须要指定commands。

如下图所示:

centos redis 查询list长度 centos7查看redis状态_redis_17

这里有两种方式进入redis-cli 来操作redis。

这里不管用哪种方式,必须要进入到Redis的默认安装路径 /usr/local/bin 的目录下进行操作。

①:需要直接指定commands

redis-cli -h 127.0.0.1 -p 6379 -a 123456

出现警告: Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe. 意思是使用这种方式不安全。使用下面方式就不会出现这种情况。

②:进入redis-cli的交互控制台后输入commands。

redis-cli

然后输入。

AUTH 123456  # 123456是自己在redis.conf文件中设置的密码

完成后会显示一个OK。

centos redis 查询list长度 centos7查看redis状态_常用命令_18

图形化桌面客户端

这里使用RDM作为图形化界面的客户端。

打开RDM软件,先点击连接到 Redis 服务器,然后输入名字和虚拟机的IP地址之后,点击确定。

centos redis 查询list长度 centos7查看redis状态_java_19

连接Redis可能会出现的问题

连接RDM失败的原因有两种

①:没有输入密码

如果你在redis.conf配置文件中设置了密码,那么这里需要输入你设置的密码。如果没有设置,那么就是属于下面的情况。

centos redis 查询list长度 centos7查看redis状态_redis_20

②:没有关闭防火墙

首先输入下述命令,查看防火墙的状态。

systemctl status firewalld

如果它这里显示 active(running),意思是防火墙开启,我们需要使用下述命令对它进行关闭。

centos redis 查询list长度 centos7查看redis状态_spring boot_21

# 关闭防火墙的命令
systemctl stop firewalld

Redis的常用命令

Redis的数据结构介绍

Redis是一个key-value的数据库,key一般是String,value的类型有多种。

基本类型

数据类型

存储数据示例

String

Hello World

Hash

{name:“Tom”,age:18}

List

[A,B,C,C]

Set

{A,B,C}

SortedSet

{A:1,B:2,C:3}

特殊类型

数据类型

存储类型示例

GEO

{A:(10.5,.22.5)}

BitMap

0110110101110101011

HyperLog

0110110101110101011

操作通用命令

查看Redis的操作命令的类型

我们可以通过两种方式来查看操作Redis命令。

①:我们可以在Redis官网查看这些命令。
②:我们可以在redis-cli的交互控制台查看命令。具体操作看下述命令。

# 进入redis-cli的交互控制台
redis-cli  
# 输入密码,这里账号可以省略
AUTH 123456  # 这里输入自己在redis-conf配置文件中设置的密码

# 查看Redis的操作命令的类型
help

# 查看Redis的通用操作命令
help @generic

# 查看某一个命令的具体用法,这里查看keys命令的用法
# help [command]
help keys

centos redis 查询list长度 centos7查看redis状态_java_22

使用常用的通用命令

KEYS查看符合模板的所有key不建议在生产环境设备上使用,因为如果存在很多个key,那么会影响到查询效率,并且在查询key的时候,Redis进程会阻塞。

KEYS pattern
# 查询所有的key  
KEYS *
# 模糊查询key 例:查询name
KEYS n*

DEL删除一个指定的KEY

DEL key
# 例:删除name
DEL name

EXISTS判断key是否存在

EXISTS key
# 例:判断 name 是否存在,如果存在会返回1,不存在返回0.
EXISTS name

EXPIRE给一个key设置有效期,有效期到期时该key会自动删除

EXPIRE key seconds
# 例:给name设置10s的有效期
EXPIRE name 10

TTL查看一个KEY的剩余有效期

TTL key
# 例:查看 name 的剩余有效期
TTL name

操作String的常用命令

String类型也就是字符串类型,是Redis中最简单的存储类型。其中value是字符串,而根据字符串的格式不同,又可以分为3类。

  1. string: 普通字符串。
  2. int:整数类型,可以做自增、自减操作。
  3. float:浮点类型:可以做自增、自减操作。

注意:不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m。

SET添加或修改已经存在的一个String类型的键值对。

SET key value
# 例:添加一个键值对 age:10
SET age 10
# 例:修改一个键值对 name:lisi
SET name lisi

GET根据key获取String类型的value

GET key
# 例:获取name的值
GET name

MSET批量添加多个String类型的键值对

MGET key value [key value ...]
# 例:添加两个键值对, email:"123@qq.com" height:178
MSET email 123@qq.com height 178

MGET根据多个key获取多个String类型的value

MGET key [key ...]
# 例:获取 email、name 的值
MGET email name

INCR让一个整型的key自增1

INCR key
# 例: 将age的年龄增加一岁
INCR age

INCRBY让一个整型的key按照指定的步长增长

INCRBY key increment
# 例:将age的年龄增加两岁
INCRBY age 2

INCRBYFLOAT让一个浮点类型的key按照指定的步长增长

INCRBYFLOAT key increment
# 例:将 num 的数增加2.5
INCRBYFLOAT num 2.5

SETNX添加一个String类型的键值对,前提是这个key不存在,否则不执行

SETNX key value
# 例:添加 name:wang 键值对,但是因为这个键存在,所以添加失败。
SETNX name wang  # 添加失败
SETNX total 100 # 添加成功

SETEX添加一个String类型的键值对,并且指定有效期

SETEX key seconds value
# 例:添加一个携带10s的键值对,name:wu
setex name wu 10

操作Key的层级结构的常用命令

Redis的key允许有多个单词形成层级结构,多个单词之间用 ‘:’ 隔开,格式如 项目名:业务名:类型:id。这个格式是不固定的,可以根据自己的需求来添加或删除词条。

如果value值是一个Java对象,则可以将此对象序列化为JSON字符串存储

KEY

VALUE

movie:user:1

{“id”:1,“name”:“Tom”}

movie:type:1

{“id”:1,“name”:“悬疑”}

语法

set key value

例子:

# 存储一个JSON格式字符串的对象
set movie:user:1 '{"id":1,"name":"Tom"}'

操作Hash的常用命令

Hash类型也叫散列,其中的value是一个无序字典,类似于Java中的HashMap结构。

String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便。因此我们使用Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD

centos redis 查询list长度 centos7查看redis状态_常用命令_23

常见命令:

HSET添加或修改hash类型key的field的值

# 这个可以添加多个
HSET key field value [field value]
# 例:添加key为movie:user:2的键,value对应的field分别为id和name,其值对应为1和Tom
HSET movie:user:2 id 1 name Tom

HGET获取一个hash类型key的field的值

HGET key field
# 获取key为movie:user:2,其field为id的值。
HGET movie:user:2 id

HMSET批量添加hash类型key的field的值

HMSET key field value [field value]
# 例:添加key为movie:user:3的键,value对应的field分别为id和name,其值对应为1和Tom
HSET movie:user:3 id 1 name Tom

HMGET批量获取多个hash类型key的field的值

HGET key field
# 获取key为movie:user:3,其field为id和name的值。
HMGET movie:user:3 id name

HGETALL获取一个hash类型的key中所有的field和value的值

HGETALL key
# 获取key为movie:user:3中所有的field和value的值。
HGETALL movie:user:3

HKEYS获取一个hash类型的key中所有field

HKEYS key
# 获取key为movie:user:3中所有的field
HMGET movie:user:3

HVALS获取一个hash类型的key中所有value

HVALS key
# 获取key为movie:user:3中所有的value
HVALS movie:user:3

HINCRBY让一个hash类型key的字段值自增并指定步长

HVALS key field increment
# 让key为movie:user:3中的id字段增加3
HINCRBY movie:user:3 id 3

HSETNX添加一个hash类型的key的field的值,前提是这个field不存在,否则不执行

HVALS key field value
# key为movie:user:3中,添加一个field为age的字段。
# 注意:如果存在,则添加失败,如果不存在,则成功。
HSETNX movie:user:3 age 15

操作List的常用命令

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构,既可以支持正向检索,也可以支持反向检索。经常用来存储一个有序数据,如朋友圈点赞列表,评论列表等。

特点

  1. 有序
  2. 元素可以重复
  3. 插入和删除快
  4. 查询速度一般

常见命令

LPUSH向列表左侧插入一个或多个元素。

LPUSH key element [element ...]
# 向key为movie:user:4的列表左侧依次插入1,2,3
LPUSH movie:user:4 1 2 3

LPOP移除并返回列表左侧的第一个元素,没有则返回NIL

LPOP key
# 移除key为movie:user:4的列表左侧的第一个元素
LPOP movie:user:4

RPUSH向列表右侧插入一个或多个元素

RPUSH key element [element ...]
# 向key为movie:user:4的列表右侧依次插入1,2,3
RPUSH movie:user:4 4 5 6

RPOP移除并返回列表右侧的第一个元素,没有则返回NIL

RPOP key
# 移除key为movie:user:4的列表右侧的第一个元素
RPOP movie:user:4

LRANGE返回一段角标范围内的所有元素

LRANGE key start stop
# 返回key为movie:user的角标为 0-1的元素
LRANGE movie:user:4 0 1

BLPOP和BRPOP:与LPOP和RPOP类似,是在没有元素时等待指定时间,而不是直接返回NIL。如果存在key,则直接返回key对应的元素。

BLPOP/BRPOP key [key...] timeout
# 注意,这里要开两个redis-cli交互控制台,否则无法完成测试
# 在第一个redis-cli交互控制台中,在key为movie:user:5的key中设置20s的等待时间
BLPOP movie:user:5 20
# 在第二个交互控制台中,向key为movie:user:5的key中向列表右侧插入 1 2 3 元素。
BPUSH movie:user:5 1 2 3
# 此时发现,在第一个redis-cli的交互控制台中出现了插入的 1 2 3元素,以及等待的时间。

思考

  1. 如何利用List结构模拟一个栈?
    元素的入口和出口在同一边
  2. 如何利用List结构模拟一个队列?
    元素的入口和出口在不同边
  3. 如何利用List结构模拟一个阻塞队列?
    入口和出口在不同边
    出队时采用BLPOP和BRPOP

操作Set的常用命令

Redis的Set结构与Java中的HashSet类似,可以看做是value为null的HashMap。因为也是一个hash表,它与HashSet类似的特征。

特点

  1. 无序
  2. 元素不可重复
  3. 查找快
  4. 支持交集、并集、差集等功能。

常见命令

SADD向set中添加一个或多个元素

SADD key member [member ...]

SREM移除set中指定元素

SREM key member [member ...]

SCARD返回set中元素的个数

SCARD key

SISMEMBER:判断一个元素是否存在与set中。

SISMEMBER key member

SMEMBERS:获取set中的所有元素。

SMEMBERS key

SINTER:求key1和key2的交集。

# 创建两个set集合,分别是1,2,3,4和1,2,6,8,求它俩的交集。
SADD a 1 2 3 4
SADD b 1 2 6 8
SINTER a b

SADD:求key1和key2的差集。

# 创建两个set集合,分别是1,2,3,4和1,2,6,8,求它的差集。
SADD a 1 2 3 4
SADD b 1 2 6 8
SDIFF a b

SUNION:求key1和key2的并集。

# 创建两个set集合,分别是1,2,3,4和1,2,6,8,求它的并集。
SADD a 1 2 3 4
SADD b 1 2 6 8
SDIFF a b

Set命令的练习

将下列数据用Redis的Set集合来存储:

  • 张三的好友有:李四.王五.赵六
  • 李四的好友有:王五.麻子.二狗

利用Set的命令实现下列功能:

  • 计算张三的好友有几人
  • 计算张三和李四有哪些共同好友
  • 查询哪些人是张三的好友却不是李四的好友
  • 查询张三和李四的好友总共有哪些人
  • 判断李四是否是张三的好友
  • 判断张三是否是李四的好友
  • 将李四从张三的好友列表中移除

代码

# 准备数据
SADD zs ls ww zl
SADD ls ww mz eg

# 计算张三的好友有几人
SCARD zs
# 计算张三和李四有哪些共同好友
SINTER zs ls
# 查询哪些人是张三的好友却不是李四的好友
SDIFF zs ls
# 查询张三和李四的好友总共有哪些人
SUNION zs ls
# 判断李四是否是张三的好友
SISMEMBER ls zs
# 判断张三是否是李四的好友
SISMEMBER zs ls
# 将李四从张三的好友列表中移除
SREM zs ls

操作SortedSet的常用命令

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList) 加hash表。因为SortedSet有可排序的特性,所以可以用来实现排行榜的功能

特点

  1. 可排序
  2. 元素不重复
  3. 查询速度快

常见命令

ZADD添加一个或多个元素到SortedSet ,如果已经存在则更新其score值

ZADD key score member [score member]

ZREM 删除SortedSet中的一个指定元素

key member [member]

ZSCORE 获取SortedSet中的指定元素的score

ZSCORE key member

ZRANK获取SortedSet中指定元素的排名

ZRANK key member

ZCARD获取SortedSet中的元素个数

ZCARD key

ZCOUNT统计score值在给定范围内的所有元素的个数

ZCOUNT key min max

ZINCRBY 让SortedSet中的指定元素自增,步长为指定的increment的值

ZINCRBY key increment member

ZRANGE按照score排序后,获取指定排名范围内的元素

ZRANGE key min max

ZRANGEBYSCORE按照score排序后,获取指定score范围内的元素

ZRANGEBYSCORE key min max

ZDIFF、ZINTER、ZUNION求差集、交集、并集

ZDIFF numkeys key  # 求差集
ZINTER numkeys key  # 求交集
ZUNION numkeys key	# 求并集

注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可

SortedSet命令练习

将班级的下列学生得分存入Redis的SortedSet中:

jack 85,lucy 89,rose 82,tom 95,jerry 78, amy 92,miles 76。并实现下列功能:

# 准备环境
zadd class 85 jack 89 lucy 82 rose 95 tom 78 jerry 98 amy 76 miles
  • 册除tom同学。
ZREM class tom
  • 获取amy同学的分数。
ZSCORE class amy
  • 获取rose同学的排名。
# 注意下标要从0开始
ZRANK class rose
  • 查询80分以下有几个学生。
ZCOUNT class 0 80
  • 给amy同学加2分。
ZINCRBY class 2 amy
  • 查出成绩前3名的同学。
ZRANGE class 0 2
  • 查出成绩80分以下的所有同学。
ZRANGEBYSCORE  class 0 80

Redis的Java客户端

经常使用的客户端有下面几种

Jedis:以Jedis命令作为方法名称,学习成本低,简单实用。但是Jedis实例是线程不安全多线程环境下需要基于连接池来使用
lettuce:Lettuce是基于Netty实现的,支持同步、异步和响应式编程方式,并且线程是安全的。支持Redis的哨兵模式、集群模式和管道模式
Redission:Redission是一个基于Redis实现的分布式,可伸缩的Java数据结构集合。包含了Map、Queue、Lock、Semaphore、AtomicLong等强大功能。

Jedis

使用步骤

  1. 引入依赖
  2. 创建Jedis对象,建立连接
  3. 使用Jedis,方法名和Redis命令一致
  4. 释放资源

导入下面依赖

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

代码实现

// 建立连接
Jedis jedis = new Jedis("192.168.31.84",6379);
// 设置密码
jedis.auth("123456");
// 这里可以选择16个库中的任意一个,注意,下标从0开始
jedis.select(1);

// 向redis中插入数据,其方法名称就是redis的命令名称
String result = jedis.set("name", "李四");
System.out.println(result);
// 获取数据
String name = jedis.get("name");
System.out.println(name);

// 释放资源
if(jedis != null){
    jedis.close();
}

Jedis的连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用Jedis连接池代替Jedis的直连方式。

在数据库连接池、tomcat中的线程池等都用到了池化思想

代码实现

public class JedisFactory {
    private static final JedisPool jedisPool;
    // 静态代码块:会随着类的加载而加载,确保只能执行一次,我们在加载当前这个工厂类的时候,就可以执行static的操作,完成对连接池的初始化。
    static {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8); // 设置资源池中的最大连接数
        poolConfig.setMaxIdle(8); // 设置资源池允许的最大连接数
        poolConfig.setMinIdle(0); // 设置资源池确保的最少空闲连接数
        poolConfig.setMaxWait(Duration.ofMillis(1000)); // 设置1000ms的等待时间
        // 创建连接池对象
        jedisPool = new JedisPool(poolConfig,"192.168.31.84",6379,1000,"123456");
    }
    // 返回连接池中的Jedis对象
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

主方法

// 建立连接
 Jedis jedis = JedisFactory.getJedis();

 // 向redis中插入数据,其方法名称就是redis的命令名称
 String result = jedis.set("name", "李四");
 System.out.println(result);
 // 获取数据
 String name = jedis.get("name");
 System.out.println(name);

 // 释放资源
 if(jedis != null){
     jedis.close();
 }

代码说明
上边使用到了工厂设计模式来完成,我们就不需要new Jedis对象,而是使用的是连接池对象,这样直接降低了耦合。当我们使用了连接池后,当我们关闭连接其实并不是关闭,而是将Jedis还回连接池的

SpringDataRedis

SpringData是Spring中数据操作的模块,包含了对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis。

  1. 它提供了对不同Redis客户端的整合(Lettuce和Jedis)。
  2. 它提供了RedisTemplate统一API来操作Redis
  3. 它支持Redis的发布订阅模型
  4. 它支持Redis的哨兵和Redis集群
  5. 它支持基于Lettuce的响应式编程
  6. 它支持JDK、JSON、字符串、Spring对象数据的序列化及反序列化
  7. 它支持基于Redis的JDKCollection实现。

RedisTemplate工具类的API说明

API

返回值类型

说明

redisTemplate.opsForValue()

ValueOperations

操作String类型的数据

redisTemplate.opsForHash()

HashOperations

操作Hash类型的数据

redisTemplate.opsForList()

ListOperations

操作List类型的数据

redisTemplate.opsForSet()

SetOperations

操作Set类型的数据

redisTemplate.opsForZSet()

ZSetOperations

操作SortedSet类型的数据

redisTemplate

通用的命令

注意:后面使用到的StingRedisTemplate与此API很相似。只不过它里面所有类型存储的都是字符串类型的

具体操作使用

①:导入依赖

<!-- redis依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池依赖 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.2</version>
</dependency>

②:配置文件

spring.redis.host=192.168.31.84
spring.redis.port=6379
spring.redis.password=123456
# 最大连接数
spring.redis.lettuce.pool.max-active=8 
# 最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 最小空闲连接
spring.redis.lettuce.pool.min-idle=0
# 连接等待时间
spring.redis.lettuce.pool.max-wait=100

③:代码实现

@Resource
    private RedisTemplate redisTemplate;
    @Test
    public void testString(){
        // 插入一条string类型的数据
        redisTemplate.opsForValue().set("name","李四");
        // 读取string类型的数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
我们可以发现使用这种方式在redis中设置的值都是序列化后的结果。

centos redis 查询list长度 centos7查看redis状态_Redis_24

总结
RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式默认是采用JDK序列化。

缺点:①:可读性差。②:内存占用较大。

因此我们需要进行序列化,这里有两种序列化方式。

解决向Redis中存储数据的乱码问题

使用RedisTemplate自定义序列化的方式

默认使用的是JdkSerializationRedisSerializer序列化,现在我们改为用GenericJackson2JsonRedisSerializer序列化。

导入Jackson依赖

<!-- Jackson依赖-->
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
</dependency>

编写代码

@Configuration
public class RedisTemplateConfiguration {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化(strkey和HashKey)
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // 设置value的序列化(value和hashValue)
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        // 返回值
        return redisTemplate;
    }
}

出现问题:在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis中,会带来额外的内存开销。

使用StringRedisTemplate方式的序列化

JSON序列化器会将类的class类型写入json结果中,并且存入Redis中,这样会产生内存空间的浪费。因此,我们将不会使用JSON序列化器来处理value,而是使用String序列化器,即只能存储String类型的Key和Value。当需要存储Java对象时,手动完成对象的序列化和反序列化

Spring提供了一个StringRedisTemplate类,它的key和value的序列化方式默认是String方式。省去了RedisTemplate的过程。

代码实现

@Resource
private StringRedisTemplate stringRedisTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
@Test
public void testStringTemplate() throws JsonProcessingException {
    // 准备对象
    User user = new User(2, "李四");
    // 准备序列化
    String userJson = mapper.writeValueAsString(user);
    // 向redis中添加一条数据
    stringRedisTemplate.opsForValue().set("user:movie:8",userJson);
    // 读取数据
    String result = stringRedisTemplate.opsForValue().get("user:movie:8");
    User readValue = mapper.readValue(result, User.class);
    System.out.println(readValue);
}

注意:这里我们将数据写入Redis时,手动的把对象序列化为JSON格式。当读取Redis中的数据时,手动把读取到的JSON反序列化为对象

RedisTemplate与StringRedisTemplate的不同点

不同点

RedisTemplate

StringRedisTemplate

序列化策略不同

默认是JDK的序列化策略

采用String的序列化策略

具体操作类型不一样

可以对任意类型的key-value的键值对操作

只能对string类型的键值对进行操作

总结:如果Redis中存储的是String类型的数据,那么就使用StringRedisTemplate取数据。如果存储的是复杂类型的数据,则使用RedisTemplate取数据。

Hash类型数据的操作

代码实现

@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
public void testHash(){
    stringRedisTemplate.opsForHash().put("user:movie:9","id","1");
    stringRedisTemplate.opsForHash().put("user:movie:9","name","李四");
    Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:movie:9");
    System.out.println(entries);
}

List类型数据的操作

代码实现

@Test
public void testList(){
    stringRedisTemplate.opsForList().leftPush("list","1");
    stringRedisTemplate.opsForList().leftPush("list","2");
    String list = stringRedisTemplate.opsForList().leftPop("list");
    System.out.println(list);
}

Set类型数据的操作

代码实现

@Test
public void testSet(){
    stringRedisTemplate.opsForSet().add("set","1","2","3");
    String set = stringRedisTemplate.opsForSet().pop("set");
    System.out.println(set);
}

SortedSet类型数据的操作

代码实现

@Test
public void testSortedSet(){
    stringRedisTemplate.opsForZSet().add("class","李明",78);
    stringRedisTemplate.opsForZSet().add("class","小红",90);
    stringRedisTemplate.opsForZSet().add("class","小刘",79);
    Long count = stringRedisTemplate.opsForZSet().count("class", 0, 80);
    System.out.println(count);
}