redis客户端选型-Jedis、lettuce、Redisson

redis客户端选型-Jedis、lettuce、Redisson,第1张

1背景

    研发部门对于客户端选型比较广泛和随意,依赖的分支也不统一,感觉就像百度到一个就直接用,或者是有一个功能满足就换,没有考虑到其他组的使用情况以及集中维护。

    另外一个是如果作为公司pom脚手架的基本组成部分,需要考虑统一成一个还是多个并存的问题,现在有两个考量:如果性能不是大问题,建议统一集中为一个就行; 如果需要多个并存,至少不能多于2个客户端。

2比较

    官方推荐的java客户端只有Jedis、lettuce、Redisson,所以这次分析只针对这三个进行。

21概述

    Jedis: redis的Java实现客户端,提供了比较全面的Redis命令的支持。

    lettuce: Lettuce is a scalable thread-safe Redis client for synchronous, asynchronous and reactive usage Multiple threads may share one connection if they avoid blocking and transactional operations such as BLPOP and MULTI/EXEC Lettuce is built with netty Supports advanced Redis features such as Sentinel, Cluster, Pipelining, Auto-Reconnect and Redis data models

    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),从而让使用者能够将精力更集中地放在处理业务逻辑上。

lettuce: 直接看官网的: >共同点:都提供了基于Redis *** 作的Java API,只是封装程度,具体实现稍有不同。

不同点:

是Redis的Java实现的客户端。支持基本的数据类型如:String、Hash、List、Set、Sorted Set。

特点:使用阻塞的I/O,方法调用同步,程序流需要等到socket处理完I/O才能执行,不支持异步 *** 作。Jedis客户端实例不是线程安全的,需要通过连接池来使用Jedis。

优点点:分布式锁,分布式集合,可通过Redis支持延迟队列。

用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以 *** 作单个Lettuce连接来完成各种 *** 作。

maven配置引入,(要加上版本号,我这里是因为Parent已声明)

application-devyml

redisson-configyml

或者,配置 redisson-configjson

新建读取配置类

或者,在 applicationyml中配置如下

431 丰富的jar支持,尤其是对 Netty NIO框架

432 丰富的配置机制选择,这里是详细的配置说明

关于序列化机制中,就有很多

433 API支持(部分展示),具体的 Redis --> RedissonClient ,可查看这里

434 轻便的丰富的锁机制的实现

参考 RedisTemplate 配置。

另外,还需要额外的配置类

基于spring缓存实现

Spring对Redis的支持是通过Spring Data Redis实现的,JedisConnectionFactory为我们提供了Redis的一种Java客户端Jedis。本文主要为大家介绍使用工厂类获取Jedis的两种方式,以及使用过程中存在的问题,希望能为大家提供一些思路。

工具/材料

IntelliJ IDEA

01

首先我们需要编辑Spring的配置文件applicationproperties,添加Redis的相关配置,这些配置在代码中需要注入,用来生成JedisConnectionFactory的Bean。

02

接下来我们写一个配置类,该配置类上需要添加@Configuration注解,我们在这个类中通过@Value注解注入applicationproperties配置文件中的部分需要的属性,其中{}用于接收属性值,在属性名冒号后面的值是默认值,若读取不到该属性则使用默认值。我们在该类中创建JedisConnectionFactory的Bean,在这个Bean中设置读取到的属性值。

03

接下来我们创建一个RedisServer的类,主要用于获取Redis以及实现部分Redis *** 作的方法。在该类中我们可以使用@Autowired注解注入JedisConnectionFactory的Bean。下图中获取Redis客户端Jedis的方法是我们推荐的方法,使用该方法我们既获取到了Jedis实例又使用的连接池,将Jedis实例交由连接池管理,不用太担心并发 *** 作导致的Redis不可用的情况。最后再附上Jedis *** 作存储和获取数据的方法。

04

另外,我们还有再介绍一种并不推荐的写法,如下图所示。这种方法每次都创建一个新的Redis连接并且没有关闭连接,在大量并发 *** 作时会带来性能上的开销,由于对连接数没有限制,可能会耗尽Redis的连接,导致Redis连接报错。

05

配置完成后我们来测试一下Jedis是否能正常使用,创建一个RedisController类,在该类中注入JedisServer,使用JedisServer提供的存储和读取方法,然后启动服务。

06

服务启动后我们在postman中进行测试,首先调用setRedis请求将数据存入Redis中,然后再调用getRedis请求获取数据,如下图所示。

07

JedisConnectionFactory在Spring Data Redis 20后就不再推荐上述这种配置方式了,当我们的spring-boot-starter-parent版本设置为2x时,我们可以看到代码中的设置已经被废弃了。

08

Spring Data Redis 20推荐使用Standalone、Sentinel、RedisCluster这三种模式的环境配置类,以便于更加灵活的适配更多的业务场景,我们一般自己测试Redis通常使用的都是单机版的,那么以单机版为例,JedisConnectionFactory的配置应写为如下的方式。

特别提示

本文只是介绍了一种Redis客户端的使用方式,还是推荐大家使用spring-boot集成Redis做开发,因为spring-boot开箱即用的特性可以大大减少开发工作量。

/
@param args
/
public static void main(String[] args) {
//连接 redis 服务
Jedis jedis = new Jedis( "1921688815" ,6379);
//密码验证-如果你没有设置 redis 密码可不验证即可使用相关命令
// jedisauth(" abcdefg ");
//简单的key-value 存储
jedisset( "redis" , "myredis" );
System out println(jedisget( "redis" ));
//在原有值得基础上添加,如若之前没有该key,则导入该key
//之前已经设定了 redis 对应" myredis ",此句执行便会使 redis 对应"myredisyourredis "
jedisappend( "redis" , "yourredis" );
jedisappend( "content" , "rabbit" );
// mset 是设置多个key-value值 参数(key1,value1,key2,value2,, keyn , valuen)
// mget 是获取多个key所对应的value值 参数(key1,key2,key3,, keyn ) 返回的是个list
jedismset( "name1" , "yangw" , "name2" , "demon" , "name3" , "elena" );
System out println(jedismget( "name1" , "name2" , "name3" ));
//map
Map<String,String> user = new HashMap<String,String>();
userput( "name" , "cd" );
userput( "password" , "123456" );
//map存入 redis
jedishmset( "user" , user);
// mapkey 个数
System out println(String format ( "len:%d" , jedishlen( "user" )));
//map中的所有键值
System out println(String format ( "keys: %s" , jedishkeys( "user" ) ));
//map中的所有value
System out println(String format ( "values: %s" , jedishvals( "user" ) ));
//取出map中的name字段值
List<String> rsmap = jedishmget( "user" , "name" , "password" );
System out println(rsmap);
//删除map中的某一个键值 password
jedishdel( "user" , "password" );
System out println(jedishmget( "user" , "name" , "password" ));
//list
jedisdel( "listDemo" );
System out println(jedislrange( "listDemo" , 0, -1));
jedislpush( "listDemo" , "A" );
jedislpush( "listDemo" , "B" );
jedislpush( "listDemo" , "C" );
System out println(jedislrange( "listDemo" , 0, -1));
System out println(jedislrange( "listDemo" , 0, 1));
//set
jedissadd( "sname" , "wobby" );
jedissadd( "sname" , "kings" );
jedissadd( "sname" , "demon" );
System out println(String format ( "set num: %d" , jedisscard( "sname" )));
System out println(String format ( "all members: %s" , jedissmembers( "sname")));
System out println(String format ( "is member: %B" , jedissismember( "sname" , "wobby" )));
System out println(String format ( "rand member: %s" , jedissrandmember("sname" )));
//删除一个对象
jedissrem( "sname" , "demon" );
System out println(String format ( "all members: %s" , jedissmembers( "sname")));
}
二、将自定义对象保存到redis中:
1、自定义pojo 实现Serializable 接口:
package cnmingyuanredis;
import javaioSerializable;
/
测试用 pojo ,实现了 Serializable ,以便进行系列化 *** 作

@author mingyuan

/
public class Person implements Serializable {
private static final long serialVersionUID = -3562550857760039655L;
private String name ;
private int age ;
public Person(){}
public Person(String name, int age) {
super ();
this name = name;
this age = age;
}
public String getName() {
return name ;
}
public void setName(String name) {
this name = name;
}
public int getAge() {
return age ;
}
public void setAge( int age) {
this age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]" ;
}
}
2、测试类:
package cnmingyuanredis;
import javaioByteArrayInputStream;
import javaioByteArrayOutputStream;
import javaioIOException;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import redisclientsjedisJedis;
public class Test {
/
@param args
@throws IOException
@throws ClassNotFoundException
/
public static void main(String[] args) throws IOException,
ClassNotFoundException {
// Jedis redis = new Jedis ("1921688815");
Jedis redis = new Jedis( "1921688815" , 6379);
// connect可以不要,因为在执行set *** 作的时候会先进行判断客户端是否于服务器端建立了连接,若无,则启动连接过程
redisconnect();
String set = redisset( "mingyuan" , "1" );
System out println( " set result \t" + set);
redisincr( "mingyuan" );
String string = redisget( "mingyuan" );
System out println( " get result of key 'mingyuan' \t" + string);
// 下面是对对象进行存储的测试代码
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
Person person = new Person( "liudehua" ,22);
ooswriteObject(person);
byte [] byteArray = bostoByteArray();
oosclose();
bosclose();
String setObjectRet = redisset( "mingyuan" getBytes(), byteArray);
System out println( " set object return \t" + setObjectRet);
byte [] bs = redisget( "mingyuan" getBytes());
ByteArrayInputStream bis = new ByteArrayInputStream(bs);
ObjectInputStream inputStream = new ObjectInputStream(bis);
Person readObject = (Person) inputStreamreadObject();
System out println( " read object \t" + readObjecttoString());
inputStreamclose();
bisclose();
redisdisconnect();
}
}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/13402494.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-29
下一篇 2023-07-29

发表评论

登录后才能评论

评论列表(0条)

保存