使用Jedis连接Redis

本文最后更新于:1 小时前

# 使用 Jedis 远程连接 Redis

# 问题描述

  • 选用 Redis 数据库,部署在 linux 之后,用 Java 语言编写一个简单的客户端去与之交互
  • 操作包括:数据插入、修改、删除等,以及和 Redis 数据库相关的特色操作

# 开发环境

  • 语言:Java11
  • 开发环境:IDEA 2021
  • 数据库:Redis 6.2
  • 数据库部署环境:CentOS Linux 8.2.2004

# Redis 环境搭建

首先使用 wget 命令获取 Redis 安装包

1
wget https://download.redis.io/releases/redis-6.2.6.tar.gz

下载Redis

然后使用 tar 命令解压

1
tar -zvxf redis-6.2.6.tar.gz

解压redis

将 redis 移动到 /usr/local/redis

1
mv redis-6.2.6 /usr/local/redis

移动redis

编译

1
2
cd /usr/local/redis
make

编译redis

安装到指定目录

1
make PREFIX=/usr/local/redis install 

安装redis

为了能使用客户机与远端数据库交互,需要修改 redis 配置文件中的 bind 项

1
2
3
4
vim redis.conf
# 修改daemonize为yes,表示开启守护进程
# 注释bind 127.0.0.1::1,表示任何ip都可以访问
# protected-mode设置为no

启动 redis 服务

1
./bin/redis-server& ./redis.conf

启动redis

查看 redis 是否正在运行

1
netstat -lanp | grep 6379

查看redis是否正常运行

# 使用客户机访问 redis

选择使用 Redis 官方提供的 Jedis 来连接 Redis,需要在 maven 中添加以下依赖:

1
2
3
4
5
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>

一共创建了两个类

  • 第一个类是 RedisOperation,其中封装了建立连接,增删改查等操作
  • 第二个类是 RedisTest 用于测试以上操作

以下是建立连接的函数,其作用是返回一个连接对象:

1
2
3
4
5
6
7
8
9
public Jedis buildConnection(String ip, int port, String password){
//指定Redis服务Host和port
Jedis jedis = new Jedis(ip, port);
//指定连接所需要的密码
jedis.auth(password);
//查看服务是否运行
System.out.println("服务正在运行:" + jedis.ping());
return jedis;
}

接下来编写主函数进行连接,并使用 ping 方法测试是否连接成功。设置默认端口号为 6379

1
2
3
4
5
6
7
8
9
10
11
public class RedisTest {
//设置默认端口为6379
public static final int DEFAULT_PORT = 6379;
//主函数
public static void main(String[] args) {
RedisOperation redis = new RedisOperation();
Jedis jedis = redis.buildConnection("这里是ip",DEFAULT_PORT,"这里是密码");
jedis.close();
}
}

运行结果如下:

建立接连

调用 jedis.ping () 方法返回了 PONG,说明连接已经建立成功,服务正在运行

# 在客户机对数据库进行增删改查

# RedisOperation 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import redis.clients.jedis.Jedis;

/**
* @author 邓智超 20192121026
* @date 2021/11/28 - 18:28
* Redis操作类,用于提供增删改查等操作
*/
public class RedisOperation {
/**
* 与远程数据库建立连接,并返回连接对象
* @param ip 服务器的ip
* @param port 端口号
* @param password 连接密码
* @return 连接对象
* */
public Jedis buildConnection(String ip, int port, String password){
//指定Redis服务Host和port
Jedis jedis = new Jedis(ip, port);
//指定连接所需要的密码
jedis.auth(password);
//查看服务是否运行
System.out.println("服务正在运行:" + jedis.ping());
return jedis;
}

/**
* 向数据库增加键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void add(Jedis jedis, String key, String value){
if(jedis != null) {
jedis.set(key, value);
}
}

/**
* 向数据库删除键值对
* @param jedis 建立的连接对象
* @param key 要删除的键值对的键
* */
public void delete(Jedis jedis, String key){
if (jedis != null) {
jedis.del(key);
}
}

/**
* 向数据库修改键值对
* @param jedis 建立的连接对象
* @param key 要修改的键值对的键
* @param value 修改后的值
* */
public void modify(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.set(key, value);
}
}

/**
* 向数据库查找键值对
* @param jedis 建立的连接对象
* @param key 要查找的键值对的键
* @return 查询到的值
* */
public String search(Jedis jedis, String key){
if (jedis != null) {
return jedis.get(key);
}
return null;
}
}

# RedisTest 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import redis.clients.jedis.Jedis;

import java.util.Scanner;

/**
* @author 邓智超 20192121026
* @date 2021/11/28 - 18:37
*/
public class RedisTest {
/**默认连接端口号*/
public static final int DEFAULT_PORT = 6379;
/**redis连接对象*/
public static Jedis jedis = null;
/**RedisOperation操作类对象*/
public static RedisOperation utility = new RedisOperation();

/**
* 向redis插入键值对
* */
public static void add(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要插入的键");
String key = scanner.next();
System.out.println("请输入要插入的值");
String value = scanner.next();
//判空
if(key == null || value == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的add()方法
utility.add(jedis, key, value);
System.out.println("插入成功");
}
}

/**
* 向删除键值对
* */
public static void delete(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要删除的键");
String key = scanner.next();
//判空
if(key == null){
System.out.println("键不能为空");
}else{
//调用操作类的delete()方法
utility.delete(jedis, key);
System.out.println("删除成功");
}
}

/**
* 向redis修改键值对
* */
public static void modify(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要修改的键");
String key = scanner.next();
System.out.println("请输入要修改的值");
String value = scanner.next();
//判空
if(key == null || value == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的modify()方法
utility.modify(jedis, key, value);
System.out.println("修改成功");
}
}

/**
* 向redis查询键值对
* */
public static void search(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要查询的键");
String key = scanner.next();
//判空
if(key == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的search()方法
String value = utility.search(jedis, key);
System.out.println("查询成功," + key + "对应的value为" + value);
}
}

public static void main(String[] args) {
RedisOperation redis = new RedisOperation();
jedis = redis.buildConnection("这里是ip",DEFAULT_PORT,"这里是密码");
//增
add();
//删
delete();
//改
modify();
//查
search();
//关闭连接
jedis.close();
}
}

# 执行结果

为了使得执行的结果更加明显,首先在服务器端中先添加几对键值对:

  • “weather” : “sunny”
  • “temperature” : “27”
  • “date” : “2021/11/28”
  • “name” : “DengZhiChao”

服务器端添加数据

增(向数据库插入 "number" : "20192121026" 的键值对):

增

在服务器端查询键 "number",可得结果 "20192121026",说明插入数据成功

服务器端验证插入结果

删(删除 weather 对应的键值对):

删

在服务器端查询所有的键,可以看见结果中没有值为 "weather" 的键,说明删除成功

服务器端查询删除结果

改(将 key 为 temperature 的 value 改成 28):

改

在服务器端查询键 "temperature",可得结果 "28",说明修改数据成功

image-20211128200420078

查(查询 name 对应的值):

查

在服务器端查询键 "name",可得结果 "DengZhiChao",说明查询数据正确

# 特色操作

# 过期键功能

Redis 是运行在内存的非关系型数据库,可以为键设置一个过期时间,让它在指定的时间之后自动被删除。此功能可以被运用在网站临时验证码的存储,让验证码到达最大存储时间后,就被自动删除。接下来,将测试此功能,考虑到时间关系,我准备将过期时间设置成 30 秒。具体的验证方式是先插入一个键值对,并标记其过期时间为 30 秒,然后在 30 秒后再次查询此键值对,若不存在,则可以验证过期键的功能。

说明:此功能在上述执行增删改查的结果基础上继续执行

RedisOperation 中的实现:

1
2
3
4
5
6
7
8
9
10
11
/**
* 设置指定键值对的过期时间
* @param jedis 建立的连接对象
* @param key 要设置过期时间的key
* @param time 多少时间后过期
* */
public void expire(Jedis jedis, String key, long time){
if (jedis != null) {
jedis.expire(key, time);
}
}

RedisTest 中的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 测试过期键功能
* */
public static void expire(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要设置过期的键");
String key = scanner.next();
System.out.println("请输入要设置过期的时间");
long time = scanner.nextLong();
//判空
if(utility.search(jedis, key) == null){
System.out.println("不存在键为" + key + "的键");
}else{
//调用操作类的expire()方法
utility.expire(jedis, key, time);
String value = utility.search(jedis, key);
System.out.println("当前" + key + "对应的value为" + value);
System.out.println("将在" + time + "秒后再次执行查询操作,请等待……");
//让程序停止一段时间
try {
Thread.sleep(time * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
value = utility.search(jedis, key);
if(value == null){
System.out.println(key + "对应的键值对已被删除,查询结果为null");
}
}
}

执行结果:

设置要过期的键为 date,过期时间为 30 秒

过期键功能

在服务器端查询所有键,发现没有 date,说明 date 对应的键值对已经过期

服务器端测试过期键结果

# 对 Redis 列表的操作

Redis 列表是简单的字符串列表,按照插入顺序排序。我们可以添加一个元素到列表的头部(左边)或者尾部(右边),接下来将分别演示向列表头部和尾部插入键值对。

说明:为了使得结果看起来更加明显,首先在服务器端创建一个 key 为 course 的列表,并向其中插入两条数据:database 和 os

原有list

RedisOperation 中的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 向Redis列表头部插入键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void lpush(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.lpush(key, value);
}
}

/**
* 向Redis列表尾部插入键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void rpush(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.rpush(key, value);
}
}

RedisTest 中的实现

头部插入:

插入列表头部

在服务器端查询 key 为 course 的列表中的全部内容,可见第一条为 linux,说明在列表头部插入成功

服务器端查询头部插入结果

尾部插入:

插入列表尾部

在服务器端查询 key 为 course 的列表中的全部内容,可见最后一条值为 CompilePrinciple,说明在列表尾部插入成功

服务器端查询尾部插入结果

# 源代码

共两个类,RedisOperation 类和 RedisTest 类

RedisOperation 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import redis.clients.jedis.Jedis;

/**
* @author 邓智超 20192121026
* @date 2021/11/28 - 18:28
* Redis操作类,用于提供增删改查等操作
*/
public class RedisOperation {
/**
* 与远程数据库建立连接,并返回连接对象
* @param ip 服务器的ip
* @param port 端口号
* @param password 连接密码
* @return 连接对象
* */
public Jedis buildConnection(String ip, int port, String password){
//指定Redis服务Host和port
Jedis jedis = new Jedis(ip, port);
//指定连接所需要的密码
jedis.auth("xxxxxxxx");
//查看服务是否运行
System.out.println("服务正在运行:" + jedis.ping());
return jedis;
}

/**
* 向数据库增加键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void add(Jedis jedis, String key, String value){
if(jedis != null) {
jedis.set(key, value);
}
}

/**
* 向数据库删除键值对
* @param jedis 建立的连接对象
* @param key 要删除的键值对的键
* */
public void delete(Jedis jedis, String key){
if (jedis != null) {
jedis.del(key);
}
}

/**
* 向数据库修改键值对
* @param jedis 建立的连接对象
* @param key 要修改的键值对的键
* @param value 修改后的值
* */
public void modify(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.set(key, value);
}
}

/**
* 向数据库查找键值对
* @param jedis 建立的连接对象
* @param key 要查找的键值对的键
* @return 查询到的值
* */
public String search(Jedis jedis, String key){
if (jedis != null) {
return jedis.get(key);
}
return null;
}

/**
* 设置指定键值对的过期时间
* @param jedis 建立的连接对象
* @param key 要设置过期时间的key
* @param time 多少时间后过期
* */
public void expire(Jedis jedis, String key, long time){
if (jedis != null) {
jedis.expire(key, time);
}
}

/**
* 向Redis列表头部插入键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void lpush(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.lpush(key, value);
}
}

/**
* 向Redis列表尾部插入键值对
* @param jedis 建立的连接对象
* @param key 要插入的键
* @param value 要插入的值
* */
public void rpush(Jedis jedis, String key, String value){
if (jedis != null) {
jedis.rpush(key, value);
}
}
}

RedisTest 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import redis.clients.jedis.Jedis;

import java.util.Scanner;

/**
* @author 邓智超 20192121026
* @date 2021/11/28 - 18:37
*/
public class RedisTest {
/**默认连接端口号*/
public static final int DEFAULT_PORT = 6379;
/**redis连接对象*/
public static Jedis jedis = null;
/**RedisOperation操作类对象*/
public static RedisOperation utility = new RedisOperation();

/**
* 向redis插入键值对
* */
public static void add(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要插入的键");
String key = scanner.next();
System.out.println("请输入要插入的值");
String value = scanner.next();
//判空
if(key == null || value == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的add()方法
utility.add(jedis, key, value);
System.out.println("插入成功");
}
}

/**
* 向删除键值对
* */
public static void delete(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要删除的键");
String key = scanner.next();
//判空
if(key == null){
System.out.println("键不能为空");
}else{
//调用操作类的delete()方法
utility.delete(jedis, key);
System.out.println("删除成功");
}
}

/**
* 向redis修改键值对
* */
public static void modify(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要修改的键");
String key = scanner.next();
System.out.println("请输入要修改的值");
String value = scanner.next();
//判空
if(key == null || value == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的modify()方法
utility.modify(jedis, key, value);
System.out.println("修改成功");
}
}

/**
* 向redis查询键值对
* */
public static void search(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要查询的键");
String key = scanner.next();
//判空
if(key == null){
System.out.println("键和值不能为空");
}else{
//调用操作类的search()方法
String value = utility.search(jedis, key);
System.out.println("查询成功," + key + "对应的value为" + value);
}
}

/**
* 测试过期键功能
* */
public static void expire(){
Scanner scanner = new Scanner(System.in);
//获取输入
System.out.println("请输入要设置过期的键");
String key = scanner.next();
System.out.println("请输入要设置过期的时间");
long time = scanner.nextLong();
//判空
if(utility.search(jedis, key) == null){
System.out.println("不存在键为" + key + "的键");
}else{
//调用操作类的expire()方法
utility.expire(jedis, key, time);
String value = utility.search(jedis, key);
System.out.println("当前" + key + "对应的value为" + value);
System.out.println("将在" + time + "秒后再次执行查询操作,请等待……");
//让程序停止一段时间
try {
Thread.sleep(time * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
value = utility.search(jedis, key);
if(value == null){
System.out.println(key + "对应的键值对已被删除,查询结果为null");
}
}
}

/**
* 向Redis列表的头部和尾部分别插入键值对
* */
public static void listInsert(){
for (int i = 0; i < 2; i++)
{
System.out.println("将向列表" + (i == 0 ? "头部" : "尾部") + "插入元素:");
//获取输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要插入的键");
String key = scanner.next();
System.out.println("请输入要插入的值");
String value = scanner.next();
if(key == null || value == null){
System.out.println("键和值不能为空");
return;
}else{
if(i == 0){
utility.lpush(jedis, key, value);
}else{
utility.rpush(jedis, key, value);
}
}
}
}


public static void main(String[] args) {
RedisOperation redis = new RedisOperation();
jedis = redis.buildConnection("这里是ip",DEFAULT_PORT,"这里是密码");
//增
add();
//删
delete();
//改
modify();
//查
search();
//测试过期功能
expire();
//从列表头部和尾部分别插入
listInsert();
//关闭连接
jedis.close();
}
}


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!