Redis 官方推荐的 Java 客户端有Jedis、lettuce 和 Redisson。三种客户端各有优缺点,在我们业务实现中选择合适的客户端,有助于提高Redis的使用性能。要选择合适的客户端我们应该大概清楚Redis客户端的通讯方式和各种客户端的优缺点。
Redis概述
Redis支持多种语言客户端,支持的客户端可以从官网查看,这里列举一系列常见的客户端:
Redis采用单线程方式处理多个客户端连接,作为程序开发者应该了解 Redis 服务端和客户端的通信协议,以及主流编程语言的 Redis 客户端使用方法,同时还需要了解客户端管理的相应 API 以及开发运维中可能遇到的问题。
Redis客户端通讯协议
Redis制定RESP(Redis Serializable Protocol, RESP)协议,实现客户端和服务端的正常交互,这种协议简单高效,既能够被机器解析,又容易被人类识别。
RESP可以序列号不同数据类型数据(整型、字符串、数组以及特殊类型Error)。需要执行的Redis命令会封装成类似字符串数组的请求通过客户端发送到服务端。Redis会基于制定的命令类型选择对应的数据类型进行回复。
Java客户端
jedis
传统老牌Java客户端,一直在更新,对redis命令有比较全面的支持。
优点
- 支持全面的Redis命令,具有全面的API。
缺点
- 阻塞式I/O,其方法都是同步调用,程序流需要等到 sockets 处理完 I/O 才能执行,不支持异步;
- Jedis 客户端实例不是线程安全的,所以需要通过连接池来使用 Jedis。
lettuce
lettuce是可扩展的线程安全的客户端,支持异步模式。如果避免阻塞和事务操作,如BLPOP和MULTI/EXEC,多个线程就可以共享一个连接。lettuce 底层基于 Netty,支持高级的 Redis 特性,比如哨兵,集群,管道,自动重新连接和Redis数据模型。
优点:
- 支持同步异步通信模式;
- Lettuce 的 API 是线程安全的,如果不是执行阻塞和事务操作,如BLPOP和MULTI/EXEC,多个线程就可以共享一个连接。
- SpringBoot 2.x默认Redis客户端,对Lettuce 提供完美支持
Redisson
Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务。其中包括( BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson 提供了使用Redis 的最简单和最便捷的方法。Redisson 的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
优点:
- 使用者对 Redis 的关注分离,可以类比 Spring 框架,这些框架搭建了应用程序的基础框架和功能,提升开发效率,让开发者有更多的时间来关注业务逻辑;
- 提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列等。
缺点: - Redisson 对字符串的操作支持比较差。
Redis Java客户端技术选型
文章基于SpringBoot 2.x进行选型
- 仅使用Redis进行字符串的数据进行缓存处理,可以使用默认的lettuce。
- 需要使用Redis做分布式事务,可以选择lettuce + Redisson。
- 需要缓存分布式集合数据并对集合进行频繁读写操作,可以选择lettuce + Redisson。
- 使用Redis 做消息队列,可以选择lettuce + Redisson。
redission使用示例
maven依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.5.7</version>
</dependency>
配置文件
spring:
redis:
database: 0
host: 192.168.159.100
port: 6379
配置类
package com.xishan.store.usercenter.userweb;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String addr;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedissonClient redisson() {
Config config = new Config();
config.useSingleServer()
.setAddress(String.format("%s%s%s", "redis://", addr,":"+port))
.setPassword(password)
.setConnectionPoolSize(64) // 连接池大小
.setConnectionMinimumIdleSize(8) // 保持最小连接数
.setConnectTimeout(1500) // 建立连接超时时间
.setTimeout(2000) // 执行命令的超时时间, 从命令发送成功时开始计时
.setRetryAttempts(2) // 命令执行失败重试次数
.setRetryInterval(1000); // 命令重试发送时间间隔
return Redisson.create(config);
}
}
测试类,使用redission方便的获取分布式锁
public void contextLoads() {
RLock sss = redissonClient.getLock("sss");
sss.lock;
sss.unlock();
}