初探 Redis 客户端 Lettuce:真香!

一、Lettuce 是啥?

一次技术谈论会上,咱们说起 Redis 的 Java 客户端哪家强,我榜首时刻毫不犹豫地喊出 “Jedis, YES!app下载

“Jedis 但是官方客户端,用起来直接省事安全期是哪几天,公司中间件都用它。除了 Jedis 外难道还有第二安全教育渠道登录个能打的?”我直接扔出王炸。

刚学 Spring 的小张听了不服:“SpringDataRedis 都用 RedisTemplate!Jedis?不存在的。”

“坐下吧秀儿,SpringDataRed线程池参数详解is 就是根据 Jedis 封装的。”周围李哥呷了一口刚开的高兴水,嘴角微微上扬,暴露一丝不屑。

“现在许多都是用 Lettuce 了,你们不会不知道吧?”老王推了推眼镜淡淡地说道,随即渐渐翻开镜片后那双心灵的窗户,用关怀的目光仰望着咱们几只菜鸡。

Lettuce?生菜?满头雾水的我赶忙翻开了 Redis 官网的客户端列表。发现 Ja源码va 言语有三个官方推荐的完毕:JedisLettuceRedission

初探 Redis 客户端 Lettuce:真香!

(截图来历:redis.io/clients#jav…)

Lettuce 是什么客户端?没听过。线程池参数详解但发现它的官方介绍最长:

Advanced Redis client for thread-safe sync, async, and reactive usage. Supports Cluster, Sentinel, Pipelining, and codecs.

赶忙查着字典翻译了下:

  • 高档客户端

  • 线程安全

  • 支撑同步、异步和反应式 API

  • 支撑集群、岗兵、管道和编解码

老王摆摆手示意我收好字典,不紧不慢介绍起来。

1.1 高档客户端

“师爷,你给app是什么意思翻译翻译,什么(哔——)叫做(哔——)高档客户端?”

“高apple级客户端嘛,高档嘛,就是 Advanced 啊!new 一下就能用,什么完毕细节都不用管,拿起事务逻辑直接突突。”

1.2 线程安全

这是和 Jedis 首要不同之一。

Jedis 的联接实例是线程不安全的,所以需求保护一个联接池,每个线程需求时从联接池取出联接实例,完毕操作后或许遇到异常偿还实例。当联接数跟着事务不断上升时,对物理联接的消耗也会成为功用和安稳性的潜在危险源码是什么意思点。

Lettuce 运用 Netty 作为通讯层线程池创立的四种组件,其联接实例是线程安全的,并且在条件具有时可安全工程专业拜访操作体系安全教育渠道原生调用 epoll, kqu线程池原理eue 等取得功用前进。

咱们知道 Redis 服务端实例尽管能够一同联接多个客户端收发指令,但每个实例实施指令时都是单线程的。

这意味着假定运用能够经过多线程+单联接办法操作 Redis,将能够精APP简 Redis 服务端的总联接数,而多运用同享同源码资本一个 Redis 服务端时也能够取得更好的安稳性和功用。关于运用来说也减少了保护多个联接实例的资源消耗。源码之家

1.3支撑同步、异步和反应式 API

Lett线程池的七个参数uce 从一开始就按照非堵塞式 IO 进行规划,是一个纯异步客户端,对异步和反应式 API 的支撑都很全面。

即使是同步指令,底层的通讯进程仍然是异步模型,仅仅经过堵塞调用线程来模拟出同步作用算了。

1.4 支撑集群、岗兵、管道application和编解码

“这些特性都是标配,Lettuce 但是高档客户端!高档,懂吗?”老王提到这儿兴奋地用手指点着桌源码之家面,但好像不想多做介绍,我默默地记下方案好好学习一番。

(在项目运用进程中,pipeling 机制用起来和 Jedis 比较稍微笼统已多线程形式怎样开点,下文会给出在运用进程中遇到的小坑和处理办法。)

1.5 在 Spring 中的运用情况

除了 Redis 官方介绍,线程池的情况咱们也能够发现 Spring Data Redis 在升安全教育渠道级到 2.0 时,将 Lettuce 升级到了 5.0。其实 Lettuce 早就在SpringDataRedis 1.6时就被官方集成了;而 SpringSessionDataRedis 则直接将 Lettuce 作为默许 Redi多线程和多进程的差异s 客户端,足见其多线程cpu有什么优点老练安全和安稳。

Jedis 广为人知乃至是事实上的规范 Java 客户端(de-facto standard driver),和它推出时刻早(1.0.0 版别 2010 年 9 月,Lettuce 1.0.0 是 2011 年 3 月)、API 直接易用多线程使用场景比如、对 Redis 新特性支撑最快等特征都密不可分。

但 Le多线程下载ttapproachuc线程池的七个参数e 作为后进,其优势和易安全教育渠道登录进口用性也取得了 Spring 等社区的喜爱。下面会同享咱们在项目中集成 Lettuce 时的经验安全期计算器总结,供咱们参看。多线程

二、Jedis 和 Lettuce 有啥首要差异?

说了这么多,Lettuce 和老牌客户端 Jedis 首要都有哪些差异呢源码买卖渠道排行?咱们能够看下Spring D线程池at线程池原理a Re安全期计算器dis帮源码买卖渠道排行助文档给出的对比表格:

初探 Redis 客户端 Lettuce:真香!

(截图来历:docs.spring.io)

注:其间 X 符号的是支撑.

经过比较咱们能够发现:

  • Jedis 支撑的线程池参数详解 Lett安全生产法uce 都支撑;

  • Jedis 不支撑的 Lettuce 也支撑!

这么看来 Spring 中越来越多地运用 Lettuce 也就不奇怪了。

三、Lettuce 初体验

光说不练假把式,给我application们同享咱们查验 Lettuce 时的收成,尤安全期计算器其是批量指令部分花了比较多的时刻踩坑,下文详解。

3.1 快速初线程池的七个参数

假定最简略的比方都令人费解,那这个库必定盛行不起来。Lettuce 的快速开始真的够快:

a. 引入 maven 依靠(其他依app下载靠相似,具体可见文末源码编辑器参看材料安全期是哪几天

<dependency>
<groupId&gt线程池回绝战略;io.lettuce</groupId安全生产法>
<安全期是哪几天ar安全教育渠道ti线程池的七个参数fact多线程和多进程的差异Id>lettuce-core</artifactId>
<version>5.3.6.RELEASE</version>
</deAPPpendency>

b. 填上 Redis 地址,联接、实施、封闭。Perfect!

import io.lettuce.core.*;
// Syntax: redis://[password@]host[:port][/databaseNumber]
// Syntax: redis://[username:password@]host[:port][/databaseNu多线程和多进程的差异mber]
RedisClient redisClient = RedisClient.create("redis://passwor源码年代d@localhost:6379线程池的七个参数/0");
StatefulRedisConnection<String, String&g线程池原理t; connection = redi线程池的七个参数sClie线程池回绝战略nt.connect();
RedisCommapplicationands<String, String> syncC源码资本ommands = connection.sync();
syncCommands.set("key", "Hello, Redis!");
conne安全教育渠道ction.close();
red安全期是哪几天isCl安全教育渠道ient.shutdown();

3.2 支撑集群形式吗?支撑!

Redis Cluster 是官方供给的 Redis Sh安全期计算器arding 方安全案,咱们应该非常熟悉不再多介绍,多线程使用场景比如官方文档可参看Redis Cluster 101。

Lettuce 联接 Redis 集群对上述客安全教育渠道登录进口户端代码一安全行换一下即可:

// Sy源码ntax: redis://[password@]host[:port]
// Syntax: redis://[username:passwordappstore@]host[:port]
RedisClusterClient redisClient = RedisClusterClient.create("redis://password@localhost:7379");

3.3 支撑高牢靠吗?支撑!

Redis Sen安全tinel 是官方供给的高牢靠方案,经过 Sentinel 能够在实例毛病时自动切换到从节点持续供给服务,安全官方文档可参看Redis Sentinel Documentation。

仍然是替换客户端的创立办法就能够了:

// Syntax: redis-sentinel://[password@]host[:port][,ho线程池参数详解st2[:por多线程使用场景比如t2]]源码是什么意思[/databaseNum安全教育ber]#se多线程是什么意思ntinelMasterId
RedisClient redisClient = RedisClient.create("redis-sentinel://localhost:26379,localhost:26380/0#mymaster");

3.4 支撑集群下的 pipeline 吗多线程并发?支撑!

Jedis 尽管有 p安全ipeline 指令appreciate,但不能支撑 Redis Cluster。一般都需求自行APP归并各个 key 所在的 slot 和实例后再批量实施 pipeline。

官网对集群下的 pipeline 支撑 PR 到本文写作时(2021年2appointment月)四年曾经了仍然未合入,线程池的七个参数可见Cluster pipelining。

Lettuce 尽管声源码是什么意思称支撑 pipeling,但并没有直接看到 pipeline 这种 API,这是怎样回事?

3.4.1 完毕 pipeline

运用 AsyncCommands 和 flushCommands 完毕 pipeline,经过阅览官方文档能够知道,Lettuce 的同步、异源码买卖渠道排行步指令其实都同享同一个联接实例,底层运用 pipeline 的形式在发送/接收安全指令。

差异在于:

  • connection.sync() 办法获取的同步指令政策,每一个操作apple都会马大将指令经过 TCP 联接发送出去;

  • connappleection.async()approach 获取的异步指令政策,实施操作后得到的是 RedisFuture<?>,在满意一定条件的情况下才批量发送。

由此我安全生产法们能够经过异步指令+手动批量推送的办法来完毕 pipeline,来看官方示例:

StaapproachtefulRedisConnection<St安全教育渠道登录ring, String> connection = client.connect();
RedisAsyncCommands<String, String> commands = connection.async();
// disable auto-flushing
commands.setAutoFlappleushCommands(false);
// perform a series of ind安全工程epen多线程形式怎样开dent calls
List<RedisFuture<?&g线程池的创立办法有几种t;> futures = Lists.newArrayList();
for (int i = 0; i < iterations; i++) {
futures.add(commands.set("key-" + i, "value-" + i));
futures.add(commands.expire("key-" + i, 3600));
}
// write all c源码年代坑人ommands to多线程形式怎样开 the transport layer
co源码之家mmands.flu源码是什么意思shCo安全教育渠道登录mmands();
// synchronization example: Wait until al源码编辑器l futures complete
boolean result = LettuceFutures.awaitAll(5, TimeUappreciatenit.SECONDS,
futures.toArray(new RedisFuture[futures.size()]));
// later
connection.close();

3.4多线程面试题.2 这么做有没有问题?

乍一看很安全教育渠道登录进口完美,但其实有暗坑:setAutoFlushCommands(false)**设置后,会发现 s线程池的情况ync() 办法调用的同步指令都不返回了!**这是为安全教育渠道什么呢?咱们源码年代坑人再看看官方文档:

Lettuce is a non-blocking and asynchronous client. It pr安全教育渠道登录ovides a synchr安全教育onous API to安全教育渠道 achieve a blocking behavior on a per-Thread basis to create await (synchronize) a command response….. As soon as the first request returns, the first Thread’s program flow continues, while the second request is processed by Redis安全教育渠道登录 and comes bac多线程cpu有什么优点k at a cerAPPtain point in time

sync 和 async 在底层完毕上都是相同的,仅仅 sync 经过堵塞调用线程的办法模拟了同步操作。并且 setAutoFlushCommands 经过源码能够发现就是作用在 connection 政策上,所以该操刁难 sync 和 async 指令政策都收效。

所以,只需某个线程中设置了 auto flush多线程形式怎样开 commands 为 false,就会影响到一切运用该联接实例的其他线程。

/源码年代坑人**
* An asynchr多线程使用场景比如onous and thread-safe API for a Redis connection.
*
* @param <K> Key type.
* @param <V> Value type.
* @author Will Glozer多线程形式怎样开
* @author Mark Paluch
*/
public abstract class AbstractRedisAsyncCommands<K, V> implements RedisHashAsyncCommands<K, V>, RedisKeyAsyncCommands<K, V>,
RedisStringAsyncCommands<K, V>, RedisListAsyncCommandsappointment<K, V>, RedisSetAsyncCom源码编辑器mands<K, V>,
RedisSortedSetAsyncCommandapples<K, V>源码下载, RedisScriptingAsyncCommands<K, V>, Re线程池的七个参数disSer安全工程verAsyncCommands线程池创立的四种<K, V>,
RedisHLLAsyncCommands<K, V>, BaseRedisAsyncCommands<K, V>, RedisTransactionalAsyncComman安全教育渠道ds线程池的创立办法有几种<K, V>,
R多线程编程edisGeoAsyncCommands&l线程池参数详解t;K, V>, R多线程和多进程的差异edisClusterAsyncCommands<K, V> {
@Override
public void setAutoFl线程池的七个参数ushCommands(boolean autoFlush) {
coapplennection.setAutoFlushCommands(autoFlush);
}
}

对应的,假定多个线程调用async()获取异步指令集,并在自身安全事务逻辑完毕后调用flushCommands(),那将会强行 flush 其他线程还在追加的异步指令,本来逻辑上归于整批的指令将被打散成多份发送。

尽管关于作用的正确性不影响,但线程池的七个参数假定因为线程相互影响打散互相的指令进行发送,则对源码年代功用的前进就会很不安稳。

自然咱们会想到:每个批指令创立一个 connection,然后……这欠好 Jedis 相同也源码是靠联接池么多线程下载

回想起老王镜片后那穿透魂灵的目光,我方案硬着头源码是什么意思皮再开掘一下。公然,再次细心阅览文档后我发现了其他一个好东西:Batch Execution多线程形式怎样开

3.4.3 Batch Execut多线程是什么意思ion

安全教育然 flushCommands 会对 connection 产生大局影响,那把 flush 约束在线程等级不就行了?我从文档中找到了示例官方示源码编辑器例。

回想线程池参数设置准则起前文 Lettuce 是高档客户端,看了文档后发现确实高档,只需求界说接口就行了(让人想起 MyBatis 的 Mapper 接口),下面是项目中运用的比方:

/
/**
* 界说会用到的批量指令
*/
@BatchSize(100)
pu安全blic interface RedisBatchQuery extends Commands, BatchExecutor {
RedisFuture<b线程池面试题yte[]> get(appstorebyte[] key);
RedisFutu多线程和多进程的差异re<Set<byte[]>> smembers(byte[] key);
RedisFuturapproache<List<byte[]>> lrange(byte[] key, long st多线程并发art, l多线程使用场景比如ong end);
RedisFuture<Map<byte[], byte[]>> hgeapp下载tall(byte[] key);
}

调用时这样操作:

// 创立客户端
RedisClusterClient client = RedisC线程池回绝战略lusterClient.create(DefaultClientResources.create(), "redis://" + address);
// service 中持有 factory 实例,只创立一次。第二个参数表明 key 和 value 运用 byte[] 编解码
RedisCommandFactory factory = new RedisCommandF源码编辑器actory(connect, Arrays.asList(ByteArrayCodec.INSTANCE, ByteArrayCodec.INSTANCE));
// 运用的当多线程使用场景比如地,创立一个查询实例署理类调用指令,终究刷入指令
List<RedisFuture<?&g源码年代t;> futures = new ArrayList<>();
RedisBatchQuery batchQuer线程池有哪几种y = factory.getCommands(RedisBatchQuery.class);
for (RedisMetaGroup redisMetaGrouapplep : redisMetaGroups) {
// 事务逻辑,循环调用多个 key 并将作用保存到 futures 作用中
appendCommand(redisMetaGroup, futures, batchQuery);
}
// 异步指令调用完毕后实施 flush 批量实施,此刻指令才会发送给多线程并发 Redis 服务端
batchQuery.flush()apple;

就是这么简略。

此刻批量的控制将在线程粒度上进行,并在调用 flush 或抵达 @BatchSize 装备的缓存指令数量时实施批量操作。而关于 connection 实例,不用再设置 auto flu多线程编程sh commands,坚持默许的 true 即可,对其他线程不构成影响。

ps:优异、谨慎的你必定会想线程池创立的四种到:假定单安全期是哪几天指令实施耗时长或许谁放了个诸如 BLPOP 的指令的话,必定会构成影响的,这个论题官方文档也有触及,能够考虑运用联接池来处理。

3.5 还能再给力一点吗?

Lettuce 支撑的当然不仅仅是上面所说的简略功用,还有这些也值得一试:

3.5.1 读写别离

咱们知道 Red线程池参数设置准则is 实例是支撑主从安置的,从实例异步地从主实例同步数据,并凭仗 Redis Sapproachentinel 在主实例毛病时进行主从切线程池参数详解换。

当运用对数据一致性不灵敏、又需求较大吞吐量时,能够考虑安全工程专业主从读写别离办法。Lettuce 能够设置 StatefulRedisClusterConnection 的 readFrom 装备来进行调整源码下载

初探 Redis 客户端 Lettuce:真香!

3.5.2 装备自动更新集群拓扑

当运用 Redis Cluster 时,服务端发生了扩容怎样办?

Lettuce 早就考虑好了——经过 RedisClusterClient#setOptions 办法传入 Clu源码下载sterClientOptions源码编辑器源码年代坑人针即可装备相源码怎样做成app软件关参数(悉数装备见文末参看链接)。

ClusterClientOptions 中的topologyRefreshOptions 常见装备如下:

初探 Redis 客户端 Lettuce:真香!

3.5.3 联接池

尽管 Lettuce 根据线程安全的单联接实例已经具有非常好的功用,但也不安全工程专业扫除有些大型事务需求经过线程池来前进吞吐application量。其他关于事务性操作是有必要独占联接的。

Lettuce 根据 Apache Common-pool2 组件供给了联接池的才干(以下是官方供给的 RedisCappreciateluster 对应的客户端线程池运用示例):

RedisClusterClient clusterClient = RedisClusterClient.create(Redi线程池sURI.create(host, port));
GenericObjectPool<StatefulRedisClusterConnection<String, String>> pool = ConnectionPoo源码资本lSupport
.crea多线程是什么意思teGenericObjectPool(() -> clusterClient.connect(), new GenericObjectPoolConfig());
// exeapp下载cute work
try (StatefulRedisCl多线程编程us多线程terC安全教育渠道onnection<String, String> connection = pool.borr安全教育渠道登录owObject()) {
connection.sync().set("key", "value");
connection.sync().blpop(10, "list");
}
// terminating
pool.close();
clusterClient.shutdown();

这儿需求阐明的是:createGenericObjectPool创立联接池默许设置wrapConnections参数为 tr源码年代ue。此刻借出的政策 close 办法将经过动态署理的办法重载为偿还联接;若设置为 false 则 close 办法会封闭联接。

Lettuce 也支撑线程池有哪几种异步的联接池(从approach联接池获取联接为异步操作),概略可参看文末链接。还有许多特性不能一一列举,都能够在官方文档上找到阐明和示例,非常值得一读。

四、运用总结

Let线程池的七个参数tuce 相较于Je多线程形式怎样开dis,运用上更加便当快捷,笼统度高。并且经过线程安全的联接降低了体系中的联接数量,前进源码买卖网站源码了体系的安稳性。

关于高档玩家,Lettuce 也供给了许多装备、接口,便当对功用进行优化和完毕深度事务定制的场景。

其他不得不说的一APP点,Lettuce 的官方文档写的非常全面细致,非常可贵。社区比较活泼,appstoreCommiter 会积极答复各类 issue,这多线程编程使得许多疑问都能够自助处多线程并发理。

比较之下,Jedis 的文档、保护更新速度就比较慢了。JedisCluste多线程r pipeline 的PR至今(2021年2月)四年以源码年代前还未合入。

参看源码资本材料

其间两个 GitHub 的 issue 含金量很高,强烈推荐一读!

1.Lettuce 快速开始:lettuce.io

2.Redis Java多线程是什么意思 Clients

3.Lettuce 官网:lettuce.io

4.SpringDataRedis参看文档

5.Question about pipelining

6.Why源码年代坑人 is Lettuce the default Redi源码年代s client use安全工程专业d in Spring Session Redis

7.Cluster-specific options:lettuce.io

8.Lettuce 联接池

9.客线程池原理户端装备:lettuce.io/core/releas…

10.SSL装备:lettuce.i线程池的情况o

作者:vivo互联网数据智能团队-Li Haoxuan

发表评论

提供最优质的资源集合

立即查看 了解详情