Redis Java Lettuce驱动框架原理解析
Lettuce是一个高性能基于Java编写的Redis驱动框架,底层集成了ProjectReactor提供天然的反应式编程,通信框架集成了Netty使用了非阻塞IO,5.x版本之后融合了JDK1.8的异步编程特性,在保证高性能的同时提供了十分丰富易用的API,5.1版本的新特性如下:
- 支持Redis的新增命令ZPOPMIN,ZPOPMAX,BZPOPMIN,BZPOPMAX。
- 支持通过Brave模块跟踪Redis命令执行。
- 支持RedisStreams。
- 支持异步的主从连接。
- 支持异步连接池。
- 新增命令最多执行一次模式(禁止自动重连)。
- 全局命令超时设置(对异步和反应式命令也有效)。
- ......等等
注意一点:Redis的版本至少需要2.6,当然越高越好,API的兼容性比较强大。
引入依赖项:
io.lettuce
lettuce-core
5.3.4.RELEASE
一、连接Redis
单机、哨兵、集群模式下连接Redis需要一个统一的标准去表示连接的细节信息,在Lettuce中这个统一的标准是RedisURI。可以通过三种方式构造一个RedisURI实例:
定制的字符串URI语法:
RedisURIuri=RedisURI.create("redis://localhost/");
使用建造器(RedisURI.Builder):
RedisURIuri=RedisURI.builder().withHost("localhost").withPort(6379).build();
直接通过构造函数实例化:
RedisURIuri=newRedisURI("localhost",6379,60,TimeUnit.SECONDS);
二、基本使用
Lettuce使用的时候依赖于四个主要组件:
- RedisURI:连接信息。
- RedisClient:Redis客户端,特殊地,集群连接有一个定制的RedisClusterClient。
- Connection:Redis连接,主要是StatefulConnection或者StatefulRedisConnection的子类,连接的类型主要由连接的具体方式(单机、哨兵、集群、订阅发布等等)选定,比较重要。
- RedisCommands:Redis命令API接口,基本上覆盖了Redis发行版本的所有命令,提供了同步(sync)、异步(async)、反应式(reative)的调用方式,对于使用者而言,会经常跟RedisCommands系列接口打交道。
一个基本使用例子如下:
RedisURIredisUri=RedisURI.builder()//<1>创建单机连接的连接信息 .withHost("localhost") .withPort(6379) .withTimeout(Duration.of(10,ChronoUnit.SECONDS)) .build(); RedisClientredisClient=RedisClient.create(redisUri);//<2>创建客户端 StatefulRedisConnectionconnection=redisClient.connect();//<3>创建线程安全的连接 RedisCommands redisCommands=connection.sync();//<4>创建同步命令 SetArgssetArgs=SetArgs.Builder.nx().ex(5); Stringresult=redisCommands.set("name","throwable",setArgs); result=redisCommands.get("name"); System.out.println(result); //...其他操作 connection.close();//<5>关闭连接 redisClient.shutdown();//<6>关闭客户端
关闭连接一般在应用程序停止之前操作,一个应用程序中的一个Redis驱动实例不需要太多的连接(一般情况下只需要一个连接实例就可以,如果有多个连接的需要可以考虑使用连接池,其实Redis目前处理命令的模块是单线程,在客户端多个连接多线程调用理论上没有效果)。
关闭客户端一般应用程序停止之前操作,如果条件允许的话,基于后开先闭原则,客户端关闭应该在连接关闭之后操作。
三、LettuceAPI
- 同步(sync):RedisCommands。
- 异步(async):RedisAsyncCommands。
- 反应式(reactive):RedisReactiveCommands。
RedisURIredisUri=RedisURI.builder() .withHost("localhost") .withPort(6379) .withTimeout(Duration.of(10,ChronoUnit.SECONDS)) .build(); RedisClientclient=RedisClient.create(redisUri); StatefulRedisConnectionconnection=client.connect();
Redis命令API的具体实现可以直接从StatefulRedisConnection实例获取,见其接口定义:
publicinterfaceStatefulRedisConnectionextendsStatefulConnection { booleanisMulti(); RedisCommands sync(); RedisAsyncCommands async(); RedisReactiveCommands reactive(); }
值得注意的是,在不指定编码解码器RedisCodec的前提下,RedisClient创建的StatefulRedisConnection实例一般是泛型实例StatefulRedisConnection
同步API
先构建RedisCommands实例
RedisCommands
redisCommands=connection.sync();
Stringpong=redisCommands.ping();
//返回PONG
System.out.println("pong:"+pong);SetArgssetArgs=SetArgs.Builder.nx().ex(5);
redisCommands.set("name","throwable",setArgs);
Stringvalue=redisCommands.get("name");
System.out.println("name:"+value);
同步API在所有命令调用之后会立即返回结果。如果熟悉Jedis的话,RedisCommands的用法其实和它相差不大。
异步API
先构建RedisAsyncCommands实例:
RedisAsyncCommands
基本使用:
RedisAsyncCommands
redisCommands=connection.async();
RedisFutureredisFuture=redisCommands.ping();
//返回PONG
System.out.println("pong:"+redisFuture.get());SetArgssetArgs=SetArgs.Builder.nx().ex(5);
RedisFuturefuture=redisCommands.set("name","throwable",setArgs);
System.out.println("name:"+future.get());
RedisAsyncCommands所有方法执行返回结果都是RedisFuture实例,而RedisFuture接口的定义如下:
publicinterfaceRedisFutureextendsCompletionStage ,Future { StringgetError(); booleanawait(longtimeout,TimeUnitunit)throwsInterruptedException; }
也就是,RedisFuture可以无缝使用Future或者JDK1.8中引入的CompletableFuture提供的方法。
反应式API
Lettuce引入的反应式编程框架是ProjectReactor,如果没有反应式编程经验可以先自行了解一下ProjectReactor。
构建RedisReactiveCommands实例:
RedisReactiveCommands
根据ProjectReactor,RedisReactiveCommands的方法如果返回的结果只包含0或1个元素,那么返回值类型是Mono,如果返回的结果包含0到N(N大于0)个元素,那么返回值是Flux。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。