介绍Java的Redis客户端和Spring的Redis客户端对比分析
Java生态里的 Redis 客户端,主流的就三个:Jedis、Lettuce、Redisson。而 Spring 的 Redis 客户端其实是指 Spring Data Redis,它本身不是底层驱动,而是对 Jedis 和 Lettuce 的统一封装。简单理解:Jedis/Lettuce 是发动机,Spring Data Redis 是方向盘,Spring Boot 2.x 之后默认用的发动机是 Lettuce。
底层客户端:Jedis vs Lettuce
先说底层这两个,因为选型时绕不开。
- Jedis:最老牌,API 方法名跟 Redis 命令几乎一一对应,学习成本极低。但它是个“裸”客户端,实例线程不安全,多线程下必须靠连接池(JedisPool)管理,而且只支持同步阻塞。
- Lettuce:基于 Netty 实现,线程安全,一个连接可以多线程复用,支持同步、异步、响应式三种编程方式,还能原生支持 Redis 哨兵和集群。
- Redisson:定位不太一样,它把 Redis 封装成了分布式的 Java 数据结构(Map、Queue、Lock 等),适合做分布式锁、分布式队列这类高级功能。
(一).前言
在介绍客户端之前,我们先要了解一些基础知识。

我们想要编写出一个自定义的Redis客户端,我们就需要知道“redis客户端”和“redis服务器”之间是通过什么协议来进行通信的。客户端按照对应的协议发送请求,然后服务器按照这个协议进行解析,然后再按照这个协议进行构造相应,客户端再解析这响应。
我们可以通过查看官网得知,redis使用的协议是RESP协议。
已经有很多人实现了这套协议的构造和解析,我们只需要使用这些提供的库,就可以比较简单方便的完成和redis服务器通信的操作了。
(二).Java的Redis客户端
在Java生态中,封装RESP协议,实现Redis的客户端有很多,这里我们使用的是jedis。
1.引入依赖
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.2</version>
</dependency>
</dependencies>2.配置端口转发
我们使用redis的时候,使用的是服务器的redis,但是我们再进行测试的时候,使用的是本机的idea,那么如果想要两者建立联系,我们需要配置端口转发。注意:一定不要开启redis的6379端口!!!因为,一旦开启了,有些“黑客”会顺着redis的端口侵入服务器。
这里我们采取的方式是,配置shh端口转发,把云服务器的redis端口,映射到本机。


此时,如果客户端访问127.0.0.1:8888,那么就相当于访问服务器的6379端口了

ssh,是一个协议,这个协议最重要的功能就是能够支持端口的转发,即通过ssh的22端口,来传递其他端口的数据
后面,我们就可以通过127.0.0.1:8888就能操作云服务器的redis了
3.连接Redis服务器
package com.spring.redis_demo;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class RedisDemoGeneric {
public static void main(String[] args) {
//连接redis服务器 通过URL描述出Redis服务器的位置
JedisPool jedisPool=new JedisPool("tcp://127.0.0.1:8888");
try (Jedis jedis = jedisPool.getResource()){ //从redis服务器连接池中取出一个对象
//redis的命令会对应到jedis对象的各种方法
String pong = jedis.ping();
System.out.println(pong);
}
}
}
可以发现,程序正常运行。注意:红色的部分不是错误
4.基础命令
(1).set和get


当测试不存在的key的时候,会返回null
注意:里面还有些setnx,setex等等方法,这里就不多演示了,都和当时介绍redis的时候一样
(2).exists和del
public static void test2(Jedis jedis){
System.out.println("exists 和 del");
jedis.flushAll();
jedis.set("k1","v1");
jedis.set("k2","v1");
jedis.set("k3","v1");
boolean k1 = jedis.exists("k1");
System.out.println("判断k1是否存在: "+k1);
long del = jedis.del("k1", "k2");
System.out.println(del);
k1 = jedis.exists("k1");
System.out.println("判断k1是否存在: "+k1);
}
(3).keys
public static void test3(Jedis jedis) {
System.out.println("keys");
jedis.flushAll();
jedis.set("k1", "v1");
jedis.set("k2", "v1");
jedis.set("k3", "v1");
Set<String> keys = jedis.keys("*");
System.out.println(keys);
}
(4).expire和ttl
public static void test4(Jedis jedis) throws InterruptedException {
System.out.println("keys");
jedis.flushAll();
jedis.set("k1", "v1");
jedis.set("k2", "v1");
jedis.set("k3", "v1");
jedis.expire("k1",60);
long k1 = jedis.ttl("k1");
System.out.println(k1);
Thread.sleep(2000);
k1 = jedis.ttl("k1");
System.out.println(k1);
}
(5).type
public static void test5(Jedis jedis) throws InterruptedException {
System.out.println("keys");
jedis.flushAll();
jedis.set("k1", "v1");
System.out.println(jedis.type("k1"));
jedis.lpush("k2","111","222","333","444");
System.out.println(jedis.type("k2"));
jedis.hset("k3","f1","v1");
System.out.println(jedis.type("k3"));
jedis.sadd("k4","1","2","3","4");
System.out.println(jedis.type("k4"));
jedis.zadd("k5",111,"111");
System.out.println(jedis.type("k5"));
}
5.各种类型的命令
(1).String
Ⅰ.mset和mget
private static void test1(Jedis jedis) {
System.out.println("mset 和 mget");
jedis.flushAll();
jedis.mset("k1","v1","k2","v2","k3","v3");
List<String> mget = jedis.mget("k1", "k2", "k3");
System.out.println(mget);
}
public static void main(String[] args) {
JedisPool jedisPool=new JedisPool("tcp://127.0.0.1:8888");
try (Jedis jedis = jedisPool.getResource()){
test1(jedis);
}
}
Ⅱ.append
private static void test2(Jedis jedis) {
System.out.println("append");
jedis.flushAll();
jedis.set("k1","aaa");
jedis.append("k1","bbb");
System.out.println(jedis.get("k1"));
}
Ⅲ.setrange 和 getrange
private static void test3(Jedis jedis) {
System.out.println("setrange 和 getrange");
jedis.flushAll();
jedis.set("k1","hello");
System.out.println(jedis.get("k1"));
jedis.setrange("k1",2,"cccc");
System.out.println(jedis.get("k1"));
String k1 = jedis.getrange("k1", 0, 2);
System.out.println(k1);
}
Ⅳ.incrby和decrby
private static void test4(Jedis jedis) {
System.out.println(" incrby和decrby ");
jedis.flushAll();
jedis.set("k1","111");
jedis.incrBy("k1",1);
System.out.println(jedis.get("k1"));
jedis.decrBy("k1",12);
System.out.println(jedis.get("k1"));
}
关于其他的类型,例如list,set,hash,zset的命令,使用的时候都一样。都是按照特定的方法,执行特定的任务。Jedis这个库,本质上就是针对redis的各种命令进行了封装,调用某个方法,就相当于在redis客户端中敲下了对应的命令
(三).Spring的客户端
1.选择对应的依赖

2.进行相应的配置
spring:
application:
name: SpringRedisBlog
data:
redis:
host: 127.0.0.1
port: 88883.具体操作

在这里我们使用的是 StringRedisTemplate这个类

可以看到,这个StringRedisTemplate相对于jedis来说,做了进一步的封装,StringRedisTemplate把这些操作redis的方法分成了一个类别,分门别类的来组织
package com.spring.redis_demo.springredisblog.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/redis")
public class MyController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/testString")
public String testString(){
//stringRedisTemplate没有封装flushall方法,所以我们只能通过connection来操作redis的原生命令
stringRedisTemplate.execute((RedisConnection connection)->{ //类似于Jedis的对象
connection.flushAll();
return null;
});
stringRedisTemplate.opsForValue().set("key1","value1");
stringRedisTemplate.opsForValue().set("key2","value2");
stringRedisTemplate.opsForValue().set("key3","value3");
stringRedisTemplate.opsForValue().set("key4","value4");
String key1 = stringRedisTemplate.opsForValue().get("key1");
String key2 = stringRedisTemplate.opsForValue().get("key2");
String key3 = stringRedisTemplate.opsForValue().get("key3");
String key4 = stringRedisTemplate.opsForValue().get("key4");
System.out.println(key1);
System.out.println(key2);
System.out.println(key3);
System.out.println(key4);
return "ok";
}
}

其他类型,以此类推,这里就不多介绍了
到此这篇关于介绍Java的Redis客户端和Spring的Redis客户端对比分析的文章就介绍到这了,更多相关java redis客户端和spring redis客户端对比内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
浅析springcloud 整合 zipkin-server 内存日志监控
Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),其主要功能是聚集来自各个异构系统的实时监控数据。这篇文章主要介绍了springcloud 整合 zipkin-server 内存日志监控,需要的朋友可以参考下2019-11-11
类添加注解@RequestMapping报错HTTP Status 404的解决
这篇文章主要介绍了类添加注解@RequestMapping报错HTTP Status 404的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-08-08
Springboot接收文件报错Required request part‘file‘is 
文章总结:在Flutter和Vue项目中遇到文件上传问题,后端接口Controller定义无误,但前端通过FormData封装上传文件时报错,通过浏览器抓包和PostMan测试,发现后台确实可以接收参数,最终通过修改封装的file为file.raw解决问题,解决了文件上传不成功的问题2025-12-12
如何解决Spring in action @valid验证不生效的问题
这篇文章主要介绍了如何解决Spring in action @valid验证不生效的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06
解决idea中Springboot找不到BASE64Encoder或Decoder的jar包
这篇文章主要介绍了解决idea中Springboot找不到BASE64Encoder或Decoder的jar包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-12-12
java中SimpleDateFormat 的多线程安全问题
本文主要介绍了java中SimpleDateFormat 的多线程安全问题,包括其内部可变状态和竞争条件,文章提供了四种解决方案,下面就来详细的介绍一下2026-02-02
java(包括springboot)读取resources下文件方式实现
这篇文章主要介绍了java(包括springboot)读取resources下文件方式实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-09-09


最新评论