Releases: redis/lettuce
5.0.0.M2
This is the second milestone release for Lettuce 5.0. We made a few breaking changes in this release:
- We moved the artifact coordinates from biz.paluch.redis:lettuce to io.lettuce:lettuce-core
- We relocated packages from biz.paluch.redis to io.lettuce.core. The migration path is straight-forward by replacing the old package name in your imports with the new package name.
- No one (not even me) knew whether it was lettuce or Lettuce when mentioning the driver on a website, mail or some documentation. We fixed that: Lettuce is now written with an uppercase L. We also have a beautiful logo and project website at https://lettuce.io.
- We removed some deprecated methods, see below for full details.
Besides the breaking changes, this release comes with 96 completed issues.
This release introduces a new reference guide that is shipped along the regular artifacts. The reference guide is bound to a particular version and does not change over time, such as the Wiki.
Lettuce defaults to native transport (epoll) on Linux systems if the epoll dependency is available. You can disable this behavior by setting the system property io.lettuce.core.epoll
to false
.
- Browse the docs at https://lettuce.io/core/5.0.0.M2/reference/
- JavaDoc: https://lettuce.io/core/5.0.0.M2/api/
Command Interface Batching
Command interfaces support command batching to collect multiple commands in a batch queue and flush the batch in a single write to the transport. Command batching executes commands in a
deferred nature. This means that at the time of invocation no result is available.
Batching can be only used with synchronous methods without a return value (void) or asynchronous methods returning a RedisFuture.
Command batching can be enabled on two levels:
- On class level by annotating the command interface with @batchsize.
All methods participate in command batching. - On method level by adding CommandBatching to the arguments.
Method participates selectively in command batching.
@BatchSize(50)
interface StringCommands extends Commands {
void set(String key, String value);
RedisFuture<String> get(String key);
RedisFuture<String> get(String key, CommandBatching batching);
}
StringCommands commands = …
commands.set("key", "value"); // queued until 50 command invocations reached.
// The 50th invocation flushes the queue.
commands.get("key", CommandBatching.queue()); // invocation-level queueing control
commands.get("key", CommandBatching.flush()); // invocation-level queueing control,
// flushes all queued commands
Read more: https://github.com/lettuce-io/lettuce-core/wiki/Redis-Command-Interfaces#batch-execution
Asynchronous Connection Propagation
Lettuce is inherently non-blocking, yet we synchronize in some places that causes blocking behavior.
Cluster node connections is one of these areas. Commands dispatched to a cluster node require a connection to be dispatched. We connected, waited until the connection is available and then we proceeded. This synchronization keeps threads busy.
With this release, we are fully non-blocking. Cluster node connections are obtained now asynchronously and we use the connection state (via CompletableFuture
) to asynchronously dispatch commands.
Asynchronous connection propagation solves a few issues such as netty deadlocks if cluster commands are sent within a future callback or in a reactive sequence.
Thanks to all contributors that made Lettuce 5.0.0 M2 possible.
Commands
- Adopt fixed GEODIST/GEOHASH behavior in tests #362
- Support CLIENT and INFO commands for Redis Sentinel #415
- Disable WAIT as Read-Only command #418
Enhancements
- Use MethodHandle.Lookup.findSpecial(…) for default method lookup #310
- Use StringCodec from Utf8StringCodec #393
- Add reactive wrapper converters for RxJava1 and 2 #383
- Provide synchronous ScanIterator API #397
- Support value ranges #384
- Allow Pub/Sub subscriptions on a node selection within Redis Cluster #385
- [BREAKING] Remove deprecated LettuceFutures.await method #388
- [BREAKING] Remove ExperimentalByteArrayCodec and enhance ByteArrayCodec #389
- Propagate backpressure to the transport channel #394
- Default to epoll transport if available #402
- Simplify NodeSelection implementation #408
- [BREAKING] Remove addListener/removeListener methods from execution-specific Pub/Sub interfaces #412
- [BREAKING] Remove close method from Redis Sentinel command interfaces #415
- Allow setting client name with RedisURI #416
- Extend RedisConnectionStateListener.onRedisConnected by adding SocketAddress #419
- Decompose array parameters into single command arguments #421
- Consider key/value type of parameter wrappers in codec resolution #423
- Connect asynchronously in cluster topology refresh #424
- Perform resilient Master/Slave topology refresh ping #424
- Return ClusterClientOptions.Builder in socketOptions and sslOptions methods #425
- Use ResolvableType for type resolution #426
- Propagate cause if cluster topology refresh can't connect to any node #427
- Propagate asynchronous connection initialization #429
- Dynamic API: Support command batching #432
- Reuse stale connections collection when closing stale connections #443
- Add ReadFrom.SLAVE_PREFERRED #452
- Share cluster node connection progress with request threads #453
- Send collection of commands as batch through StatefulConnection and ChannelWriter #456
- Use EnumSet to determine Read-Only commands #457
- Encapsulate fields in Commands implementations and command builder #458
- Refactor command creation and execution to ExecutableCommand creation #463
- Use String-Codec for COMMAND #467
- Create a static call chain in InvocationProxyFactory #468
- Initialize RedisStateMachine.LongProcessor in static initializer #481 (Thanks to @hellyguo)
- Add shutdownAsync to AbstractRedisClient #485 (Thanks to @jongyeol)
- Propagate asynchronous connections to ClusterConnectionProvider #486 (@thanks to @jeniok)
- Resolve hostnames using netty's DNS resolver #498
- Introduce NettyCustomizer API #499 (Thanks to @jongyeol)
- Use asynchronous node connect in NodeSelection #500
- Gracefully degrade to successfully connected Cluster read candidates #503 (Thanks to @eliotw)
- Implement counting Deque #507 (Thanks to @CodingFabian)
- Use ThreadLocalRandom instead of Random #510
- Replace consumer completion List in CommandWrapper with Array #511
- Consider ConnectionFuture state in ClusterDistributionChannelWriter #511
- Replace first arg fields in CommandArgs with CommandArgsAccessor #511
- Merge Command completion state fields to a single status field #511
- Move command latency metrics to LatencyMeteredCommand #511
- Close the connection when Redis protocol is corrupted #512 (Thanks to @jongyeol)
- Allow setting the Redis password as char-array #513
- Replace synchronized reconnect in ConnectionWatchdog with asynchronous connect #514
- Improve cleanup of PauseDetector #516
- Upgrade AsyncExecutions to use CompletableFuture #522
Fixes
- Update code samples in readme to Lettuce 4.0 #410
- Apply proxy wrapper to obtained pooled connections #411
- Allow databases greater than 15 in RedisURI #420
- Consider Wildcard types in type information and assignability #431
- Expose a protected default constructor for RedisClusterClient #438
- Ensure RoundRobinSocketAddressSupplier consistency before returning a SocketAddress #440
- Fix Partitions.addPartition(…) and Partitions.reload(…) synchronization #442
- Fix authenticated PING before connect with Redis Sentinel #448
- Close connections in PooledClusterConnectionProvider.close() #460
- Read connect future in ReconnectHandler to local variable #465
- Apply command timeout to PING before connection activation #470
- Synchronize ClientResources shutdown in client shutdown #475
- Skip SO_KEEPALIVE and TCP_NODELAY options for Unix Domain Socket connections #476 (Thanks to @magdkudama)
- Fix cummulative metrics collection #487 (Thanks to @ameenhere)
- Stop LatencyStats on removal #517
- Guard PauseDetectorWrapper initialization against absence of LatencyUtils #520
Other
- Upgrade to Java 9-compatible build #310
- Mark NodeSelection API as stable #389
- Document RedisClient and RedisClusterClient implementation hooks #392
- Upgrade to netty 4.1.7 #436
- Fix ClientResources usage in tests #445
- Enable JMH tests on TravisCI #454
- Create benchmarks for RedisClient, RedisClusterClient and ClusterDistributionChannelWriter #454
- Use Reactor's StepVerifier in tests #455
- Upgrade to TravisCI trusty #461
- Upgrade to Mockito 2.7.5 #469
- Improve JavaDoc #472
- Upgrade dependencies #474
- Switch optional dependencies from provided to optional #482
- Use appropriate EventLoopGroup in SingleThreadedReactiveClusterClientTest #486
- Update Netty version to 4.1.9 #489 (Thanks to @odiszapc)
- Calculate first response metrics from sent time #491
- [BREAKING] Move to lettuce.io #493
- Create reference documentation #494
- Switch to codecov #504
- Upgrade to Reactor 3.1.0 SNAPSHOT #505
- Upgrade integrations from mp911de/lettuce to lettuce-io/lettuce-core #506
- Upgrade to Project Reactor 3.1.0.M1 #523
- Upgrade to RxJava 1.2.10 #524
- Upgrade to RxJava2 2.0.9 #525
- Switch jcl-over-slf4j dependency to test scope #526
Documentation
- Browse the docs at https://lettuce.io/core/snapshot/reference/.
- JavaDoc: https://lettuce.io/core/5.0.0.M2/api/
4.3.2.Final
This release fixes several issues and some enhancements.
it ships with 17 tickets fixed.
Lettuce was moved meanwhile to a new organization in GitHub: https://github.com/lettuce-io and
has a new website at https://lettuce.io. Maven coordinates for the 4.x branch remain stable.
If you're using command latency metrics, please note that first response metrics are now
calculated from the sent time and no longer from the command completion time.
Find the full change log at the end of this document.
Thanks to all contributors who made lettuce 4.3.2 possible.
Fixes
- Read connect future in ReconnectHandler to local variable #465
- Close Standalone/Sentinel connections on connection failure #471 (Thanks to @jongyeol)
- Synchronize ClientResources shutdown in client shutdown #475
- Skip SO_KEEPALIVE and TCP_NODELAY options for Unix Domain Socket connections #476 (Thanks to @magdkudama)
- Fix cummulative metrics collection #487 (Thanks to @ameenhere)
- Stop LatencyStats on removal #517
- Guard PauseDetectorWrapper initialization against absence of LatencyUtils #520
Enhancements
- Initialize RedisStateMachine.LongProcessor in static initializer #481 (Thanks to @hellyguo)
- Apply command timeout to PING before connection activation #470
- Close the connection when Redis protocol is corrupted #512 (Thanks to @jongyeol)
- Improve cleanup of PauseDetector #516
- CommandHandler performs expensive queue check if requestQueueSize != Integer.MAX_VALUE #507 (Thanks to @CodingFabian)
Other
- Improve JavaDoc #472
- Update Netty version to 4.1.9 #489 (Thanks to @odiszapc)
- Calculate first response metrics from sent time #491
- Upgrade to RxJava 1.2.10 #524
- Switch to codecov #504
Javadoc: http://redis.paluch.biz/docs/api/releases/4.3.2.Final/
4.3.1.Final
This release fixes several issues that remained undiscovered for quite a while,
it ships with 9 tickets fixed.
Find the full change log at the end of this document.
Thanks to all contributors who made lettuce 4.3.1 possible.
Fixes
- Apply proxy wrapper to obtained pooled connections #411 (Thanks to @krisjey)
- Allow databases greater than 15 in RedisURI greater 15 #420 (Thanks to @ChitraGuru)
- Expose a protected default constructor for RedisClusterClient #438 (Thanks to @wuhuaxu)
- RoundRobinSocketAddressSupplier may contain more RedisClusterNodes than the current topology view #440 (Thanks to kojilin)
- Partitions.addPartition and reload not correctly synchronized #442
- pingBeforeActivateConnection and authentication fails using Redis Sentinel #448 (Thanks to @coolmeen)
- PooledClusterConnectionProvider.close does not close connections #460
Other
Javadoc: http://redis.paluch.biz/docs/api/releases/4.3.1.Final/
5.0.0.Beta1
This is a major release coming with several breaking changes and new interesting features. It's similar to the simultaneously released version 4.3.0 but comes with major changes.
Lettuce 5.0 removes deprecated interfaces RedisConnection
and RedisAsyncConnection
and their segregated interfaces in favor of StatefulRedisConnection
and RedisCommands
et al.
This release removes dependencies to Guava. Lettuce requires only Netty and Project Reactor which brings us to the next change. The reactive API is based on Reactive Streams by using Project Reactor types Mono
and Flux
instead of RxJava 1 and Observable
. Existing users can convert Mono
and Flux
by using rxjava-reactive-streams
.
Finally, this release introduces the dynamic Redis Commands API. This programming model enables you to declare command methods and invoke commands to your needs and support Redis Modules without waiting for lettuce to support new commands.
This beta/candidate release is to give you a chance to try out new features, get feedback and improve for the final release.
You will find the full change log at the end of this document.
Thanks to all contributors that made lettuce 5.0.0 possible.
lettuce 5.0.0 requires Java 8 and cannot be used with Java 6 or 7.
Good bye, Guava
Lettuce 5.0 no longer uses Google's Guava library. Guava was a good friend back in the Java 6-compatible days where Future
synchronization and callbacks were no fun to use. That changed with Java 8 and CompletableFuture
.
Other uses like HostAndPort
or LoadingCache
could be either inlined or replaced by Java 8's Collection framework.
Removal of deprecated interfaces and methods
This release removes deprecated interfaces RedisConnection
and RedisAsyncConnection
and their segregated interfaces in favor of StatefulRedisConnection
and RedisCommands
.
You will notice slight differences when using that API. Transactional commands and database selection are no longer available through the Redis Cluster API as the old API was derived from the standalone API. RedisCommands
and RedisAsyncCommands
are no longer Closeable
. Please use commands.getStatefulConnection().close()
to close a connection. This change removes ambiguity over closing the commands interface over closing the connection.
Migration to Reactive Streams (Project Reactor)
Lettuce 4.0 introduced a reactive API based on RxJava 1 and Observable
.
This was the beginning of reactive Redis support. Lettuce used Observable
all over the place as other reactive types like Single
and Completable
were still beta or in development.
Since that time, a lot changed in the reactive space. RxJava 2 is still in the works towards a final release supporting Reactive Streams, while other composition libraries are already available and polish on sharp edges. This means, it was just a matter of time that lettuce adopts Reactive Streams.
This also means, no null
values and usage of dedicated value types to express value multiplicity (0|1
and 0|1|N
) on the API.
With lettuce 5.0, the reactive API uses Project Reactor, Mono
and Flux
.
4.3 and earlier
Observable<Long> del(K... keys);
Observable<K> keys(K pattern);
Observable<V> mget(K... keys);
5.0
Mono<Long> del(K... keys);
Flux<K> keys(K pattern);
Flux<KeyValue<K, V>> mget(K... keys);
Switching from RxJava 1 to Project Reactor use requires switching the library. Most operators use similar or even same names. If you're required to stick to RxJava 1, the use rxjava-reactive-streams
to adopt reactive types (RxJava 1 <-> Reactive Streams).
Migrating to Reactive Streams requires value wrapping to indicate absence of values. You will find differences in comparison to the previous API and to the sync/async API in cases where commands can return null
values. Lettuce 5.0 comes with new Value
types that are monads encapsulating a value (or their absence).
See also: https://github.com/mp911de/lettuce/wiki/Reactive-API-%285.0%29
Value, KeyValue, and other value types
This release enhances existing value types and introduces new types to reduce null
usage and facilitate functional programming.
Value types are based on Value
and KeyValue
/ScoredValue
extend from there.
Value is a wrapper type encapsulating a value or its absence. A Value
can be created in different ways:
Value<String> value = Value.from(Optional.of("hello"));
Value<String> value = Value.fromNullable(null);
Value<String> value = Value.just("hello");
KeyValue<Long, String> value = KeyValue.from(1L, Optional.of("hello"));
KeyValue<String, String> value = KeyValue.just("key", "hello");
It transforms to Optional
and Stream
to integrate with other functional uses and allows value mapping.
Value.just("hello").stream().filter(…).count();
KeyValue.just("hello").optional().isPresent();
Value.from(Optional.of("hello")).map(s -> s + "-world").getValue();
ScoredValue.just(42, "hello").mapScore(number -> number.doubleValue() * 3.14d).getScore();
You will also find that all public fields of value types are encapsulated with getters and these fields are no longer accessible.
Dynamic Redis Commands API
The Redis Command Interface abstraction provides a dynamic way for typesafe Redis command invocation. It allows you to declare an interface with command methods to significantly reduce boilerplate code required to invoke a Redis command.
Redis is a data store supporting over 190 documented commands and over 450 command permutations.
Command growth and keeping track with upcoming modules are challenging for client developers and Redis user as there is no full command coverage for each module in a single Redis client.
Invoking a custom command with lettuce several lines of code to define command structures pass in arguments and specify the return type.
RedisCodec<String, String> codec = new StringCodec();
RedisCommands<String, String> commands = ...
String response = redis.dispatch(CommandType.SET, new StatusOutput<>(codec),
new CommandArgs<>(codec)
.addKey(key)
.addValue(value));
The central interface in lettuce Command Interface abstraction is Commands
. This interface acts primarily as a marker interface to help you to discover interfaces that extend this one. You can declare your own command interfaces and argument sequences where the command name is derived from the method name or provided with @Command
. Introduction of new commands does not require you to wait for a new lettuce release but they can invoke commands through own declaration. That interface could be also supporting different key and value types, depending on the use-case.
Commands are executed applying synchronization, asynchronous and in a reactive fashion, depending on the method declaration.
public interface MyRedisCommands extends Commands {
String get(String key); // Synchronous Execution of GET
@Command("GET")
byte[] getAsBytes(String key); // Synchronous Execution of GET returning data as byte array
@Command("SET") // synchronous execution applying a Timeout
String setSync(String key, String value, Timeout timeout);
Future<String> set(String key, String value); // asynchronous SET execution
@Command("SET")
Mono<String> setReactive(String key, String value); // reactive SET execution using SetArgs
@CommandNaming(split = DOT) // support for Redis Module command notation -> NR.RUN
double nrRun(String key, int... indexes);
}
RedisCommandFactory factory = new RedisCommandFactory(connection);
MyRedisCommands commands = factory.getCommands(MyRedisCommands.class);
String value = commands.get("key");
You get a whole lot new possibilities with Redis Command Interfaces. This release provides initial support. Future versions are likely to support RxJava 1/2 reactive types so RxJava 1 users have a migration path that allows using native types without further conversion.
See also: https://github.com/mp911de/lettuce/wiki/Redis-Command-Interfaces
Backoff/Delay strategies
Thanks to @jongyeol
When running cloud-based services with a multitude of services that use Redis,then network partitions impact Redis server connection heavily once the partition ends. A network partition impacts all disconnected applications at the same time and all nodes start reconnecting more or less at the same time.
As soon as the partition ends, the majority of applications reconnect at the same time. Jitter backoff strategies leverage the impact as the time of reconnecting is randomized.
Lettuce comes with various backoff implementations:
- Equal Jitter
- Full Jitter
- Decorrelated Jitter
These are configured in ClientResources
:
DefaultClientResources.builder()
.reconnectDelay(Delay.decorrelatedJitter())
.build();
DefaultClientResources.builder()
.reconnectDelay(Delay.equalJitter())
.build();
See also: https://www.awsarchitectureblog.com/2015/03/backoff.html and
https://github.com/mp911de/lettuce/wiki/Configuring-Client-resources
New API for Z...RANGE commands
Sorted Sets range commands come with a streamlined API regarding method overloads. Commands like ZRANGEBYSCORE
, ZRANGEBYLEX
, ZREMRANGEBYLEX
and several others now declare methods accepting Range
and Limit
objects instead of an growing parameter list. The new Range
allows score and value types applying the proper binary encoding.
4.2 and earlier
commands.zcount(key, 1.0, 3.0)
commands.zrangebyscore(key, "-inf", "+inf")
commands.zrangebyscoreWithScores(key, "[1.0", "(4.0")
commands.zrangebyscoreWithScores(key, "-inf", "+inf", 2, 2)
Since 4.3
commands.zcount(key, Range.create(1.0, 3.0));
commands.zrangebyscore(key, Range.unbounded());
commands.zrangebyscoreWithScores(key, Range.from(Boundary.including(1.0), Boundary.ex...
4.3.0.Final
This release fixes several issues, provides a streamlined Sorted Sets API and introduces new features for network partition recovery, zero-downtime Redis Cluster reconfiguration and improved resource handling.
Lettuce 4.3 comes with a new StringCodec
that uses optimized String encoding and decoding for UTF-8 and ASCII charsets. Encoding and decoding is up to 5x faster now.
You will find the full change log at the end of this document.
lettuce 4.3.0 is not binary compatible with the last release as it changed the signature of srandmember
to return List
instead of Set
.
Thanks to all contributors that made lettuce 4.3.0 possible.
lettuce 4.3.0 requires Java 8 and cannot be used with Java 6 or 7.
Backoff/Delay strategies
Thanks to @jongyeol
When running cloud-based services with a multitude of services that use Redis,then network partitions impact Redis server connection heavily once the partition ends. A network partition impacts all disconnected applications at the same time and all nodes start reconnecting more or less at the same time.
As soon as the partition ends, the majority of applications reconnect at the same time. Jitter backoff strategies leverage the impact as the time of reconnecting is randomized.
Lettuce comes with various backoff implementations:
- Equal Jitter
- Full Jitter
- Decorrelated Jitter
These are configured in ClientResources
:
DefaultClientResources.builder()
.reconnectDelay(Delay.decorrelatedJitter())
.build();
DefaultClientResources.builder()
.reconnectDelay(Delay.equalJitter())
.build();
See also: https://www.awsarchitectureblog.com/2015/03/backoff.html and
https://github.com/mp911de/lettuce/wiki/Configuring-Client-resources
New API for Z...RANGE commands
Sorted Sets range commands come with a streamlined API regarding method overloads. Commands like ZRANGEBYSCORE
, ZRANGEBYLEX
, ZREMRANGEBYLEX
and several others now declare methods accepting Range
and Limit
objects instead of an growing parameter list. The new Range
allows score and value types applying the proper binary encoding.
4.2 and earlier
commands.zcount(key, 1.0, 3.0)
commands.zrangebyscore(key, "-inf", "+inf")
commands.zrangebyscoreWithScores(key, "[1.0", "(4.0")
commands.zrangebyscoreWithScores(key, "-inf", "+inf", 2, 2)
Since 4.3
commands.zcount(key, Range.create(1.0, 3.0));
commands.zrangebyscore(key, Range.unbounded());
commands.zrangebyscoreWithScores(key, Range.from(Boundary.including(1.0), Boundary.excluding(4.0));
commands.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2));
Connection pooling deprecation
It took quite a while but 4.3 finally deprecates Lettuce's existing connection pooling support. That are in particular RedisClient.pool(…)
and RedisClient.asyncPool(…)
. These methods will be removed with lettuce 5.0.
Connection pooling had very limited support and would require additional overloads that clutter the API to expose pooling for all supported connections. This release brings a replacement, that is customizable and does not pollute the API. ConnectionPoolSupport
provides methods to create a connection pool accepting a factory method and pool configuration.
Returned connection objects are proxies that return the connection to its pool when calling close()
. StatefulConnection
implement Closeable
to allow usage of try-with-resources.
GenericObjectPool<StatefulRedisConnection<String, String>> pool = ConnectionPoolSupport
.createGenericObjectPool(() -> client.connect(), new GenericObjectPoolConfig());
try(StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
// Work
}
pool.close();
Redis Cluster topology refresh consensus
Cluster topology refreshing can lead in some cases (dynamic topology sources) to orphaning. This can happen if a cluster node is removed from the cluster and lettuce decides to accept the topology view of that removed node. Lettuce gets stuck with that node and is not able to use the remaining cluster.
This release introduces PartitionsConsensus
strategies to determine the most appropriate topology view if multiple views are acquired. The strategy can be customized by overriding RedisClusterClient.determinePartitions(Partitions, Map<RedisURI, Partitions>)
.
Lettuce defaults choosing the topology view with the majority of previously known cluster nodes. This helps lettuce to stick with the cluster that consists of the most nodes.
See also: https://github.com/mp911de/lettuce/issues/355
If you need any support, meet lettuce at:
- Google Group: https://groups.google.com/d/forum/lettuce-redis-client-users
- Gitter: https://gitter.im/mp911de/lettuce
- Github Issues: https://github.com/mp911de/lettuce/issues
Commands
- Add support for TOUCH command #270
- Add support for variadic LPUSHX and RPUSHX #267
- Provide a more conceise API for Sorted Set query operations using Range/Limit #363
- Add support for ZREVRANGEBYLEX command #369 (Thanks to @christophstrobl)
- Add support for SWAPDB #375
Enhancements
- Add SocketOptions to ClientOptions #269
- Add support for OpenSSL as SSL provider #249
- Replacement support for connection pooling #264
- Add ToByteBufEncoder and improved StringCodec #275
- Allow configuration of a trust store password #292
- Replace Guava Cache by ConcurrentHashMap #300
- Eager initialization of API wrappers in stateful connections #302 (Thanks to @jongyeol)
- Change MethodTranslator's loadfactor to 1.0 for sync APIs performance #305 (Thanks to @jongyeol)
- Reattempt initially failed Sentinel connections in Master/Slave API #306
- Replace synchronized setters with volatile fields #326 (Thanks to @guperrot)
- Add workaround for IPv6 parsing #332
- Provide multi-key-routing for exists and unlink commands using Redis Cluster #334
- Add ConnectionWatchdog as last handler #335
- Provide Timer as part of ClientResources #354 (Thanks to @plokhotnyuk)
- Add support for topology consensus #355
- Use Limit in SortArgs #364
- Add jitter backoff strategies for spreading reconnection timing #365 (Thanks to @jongyeol)
- Add EVAL and EVALSHA to ReadOnlyCommands #366 (Thanks to @amilnarski)
- Add support for ZADD INCR with ZAddArgs #367 (Thanks to @christophstrobl)
- Accept double in ZStoreArgs.weights #368 (Thanks to @christophstrobl)
- Consider role changes as trigger for update using MasterSlave connections #370
Fixes
- Fix JavaDoc for blocking list commands #272
- Guard key parameters against null values #287
- CommandArgs.ExperimentalByteArrayCodec fails to encode bulk string #288
- Guard value parameters against null values #291 (Thanks to @christophstrobl)
- Allow MasterSlave connection using Sentinel if some Sentinels are not available #304 (Thanks to @rahulbabbar)
- Allow coordinated cross-slot execution using Iterable #303 (Thanks to @agodet)
- Use at least 3 Threads when configuring default thread count #309
- Replace own partition host and port only if the reported connection point is empty #312
- Lettuce RedisClusterClient calls AUTH twice #313
- CommandHandler notifications called out of order #315
- Disable SYNC command #319
- Record sent-time on command queueing #314 (Thanks to @HaloFour)
- ASK bit not set on ASK redirection #321 (Thanks to @kaibaemon)
- Check for isUnsubscribed() before calling subscriber methods #323 (Thanks to @vleushin)
- Avoid timeouts for cancelling command #325 (Thanks to @jongyeol)
- Guard command completion against exceptions #331
- Store error at output-level when using NestedMultiOutput #328 (Thanks to @jongyeol)
- Fix master and slave address parsing for IPv6 addresses #329 (Thanks to @maksimlikharev)
- Fix srandmember return type from Set to List #330 (Thanks to @jongyeol)
- Add synchronization to Partitions/Use read-view for consistent Partition usage during Partitions updates #333 (Thanks to @OutOfBrain)
- Run cluster command redirects on event executor threads #340 (Thanks to @oklahomer)
- Close connections in PooledClusterConnectionProvider on connection failures #343
- Consider number of redirections instead of executions for cluster commands #344 (Thanks to @Spikhalskiy)
- Ensure unique reconnect scheduling #346
- Guard ConnectionWatchdog against NPE from missing CommandHandler #358
- Fix RedisAdvancedClusterAsyncCommandsImpl.msetnx return value #376 (Thanks to @mjaow)
- Allow hostnames in MasterSlaveTopologyProvider when parsing in master_host #377 (Thanks to @szabowexler)
- Support integer width multiplied offsets in BITFIELD #379 (Thanks to @christophstrobl)
- Propagate array sizes in MultiOutput #380 (Thanks to @christophstrobl)
Other
- Improve test synchronization #216
- Upgrade to stunnel 5.33 #290
- Upgrade rxjava to 1.1.6 #295
- Upgrade logging to log4j2 for tests #316
- Cleanup connections during test #318
- Upgrade netty to 4.0.40.Final and 4.1.4.Final #336
- Upgrade rxjava to 1.1.9 #337
- Upgrade to Guava 19 #351
- Upgrade to AssertJ 3.5.2 #352
- Upgrade netty to 4.0.41.Final and 4.1.5.Final #353
- Add test to verify behavior of GEODIST if a geoset is unknown #362
- Update license/author headers #387
- Upgrade to netty 4.0.42.Final/4.1.6.Final 390
- Upgrade to rxjava 1.2.1 391
lettuce requires a minimum of Java 8 to build and run. It is tested continuously
against the latest Redis source-build.
Javadoc: http://redis.paluch.biz/docs/api/releases/4.3.0.Final/
4.2.2.Final
This is a bugfix release that fixes several issues. Updating is recommended for
setups with frequent reconnects or frequent cluster topology changes during runtime.
Thanks to all who made this release possible.
lettuce 4.2.2 requires Java 8 and cannot be used with Java 6 or 7.
Commands
- Deprecate SYNC command #319
Fixes
- Fix sync/async/reactive methods for thread-safe #302 (Thanks to @jongyeol)
- Allow coordinated cross-slot execution using Iterable #303 (Thanks to @agodet)
- Allow MasterSlave connection using Sentinel if some Sentinels are not available #304 (Thanks to @rahulbabbar)
- Don't call AUTH in topology refresh #313
- Record sent-time on queueing #314 (Thanks to @HaloFour)
- CommandHandler notifications called out of order #315
- Fix ask redirection #321 (Thanks to @kaibaemon)
- Check for isUnsubscribed() before calling subscriber methods #323 (Thanks to @vleushin)
- Replace synchronized setters with volatile fields #326 (Thanks to @guperrot)
- Store error at output-level when using NestedMultiOutput #328 (Thanks to @jongyeol)
- Fix master and slave address parsing for IPv6 addresses #329 (Thanks to @maksimlikharev)
- Guard command completion against exceptions #331 (Thanks to @vleushin)
- Use a read-view for consistent Partition usage during Partitions updates #333 (Thanks to @OutOfBrain)
Other
- Improve test synchronization in PubSubRxTest #216
- Change MethodTranslator's loadfactor to 1.0 for sync APIs performance #305 (Thanks to @jongyeol)
- Use at least 3 Threads when configuring default thread count #309
- Replace own partition host and port only if the reported connection point is empty #312
- Add workaround for IPv6 parsing #332
- Provide multi-key-routing for exists and unlink commands using Redis Cluster #334
- Add ConnectionWatchdog as last handler #335
- Upgrade netty to 4.0.40.Final #336
- Upgrade rxjava to 1.1.9 #337
lettuce requires a minimum of Java 8 to build and run. It is tested continuously
against the latest Redis source-build.
Javadoc: http://redis.paluch.biz/docs/api/releases/4.2.2.Final/
4.2.1.Final
This is a bugfix release that fixes issues with reconnection, connection handling and unexpected connection termination. lettuce 4.2.1 is also compatible with netty 4.0 and 4.1.
lettuce 4.2.0 requires Java 8 and cannot be used with Java 6 or 7.
Commands
- Add support for TOUCH command #270
Fixes
- Add missing package-info #263
- Fix JavaDoc for blocking list commands #272
- Apply synchronous command timeout from the given context using RedisClient #273
- Ensure netty 4.1 compatibility #274
- Unschedule topology refresh on cluster client shutdown #276
- Record command upon write #277
- Disable ConnectionWatchdog when closing a disconnected connection #278
- Perform selective relocation of org.* packages #280
- Remove use of internal rx OperatorConcat class #286 (Thanks to @HaloFour)
- Fix experimental byte array Codec #288
- Guard command encoding against null #291 (Thanks to @christophstrobl)
Other
lettuce requires a minimum of Java 8 to build and run. It is tested continuously against the latest Redis source-build.
Javadoc: http://redis.paluch.biz/docs/api/releases/4.2.1.Final/
3.5.0.Final
lettuce 3.5.0 is here. This release follows the same renumbering like 4.2.0.
This release comes with SSL support for Redis Cluster, support for new commands and a series of bug fixes.
Important note for users of connection-pooling and latency tracking
Dependencies were streamlined with this release. Apache's commons-pool2
and latencyutils
are now optional dependencies. If you use connection-pooling or latency tracking, please include these dependencies explicitly otherwise these features will be disabled.
lettuce 3.5.0 is fully binary compatible with the last release and can be used as a drop-in replacement for 3.4.x. This update is strongly recommended for lettuce 3.x users as it fixes some critical connection synchronization bugs.
Thanks to all contributors that made lettuce 3.5.0 possible.
lettuce 3.5.0 requires Java 6. Please note that some commands are only available in the Redis unstable branch (such as variadic LPUSHX/RPUSHX).
Redis Cluster and SSL
Redis introduces an option to announce a specific IP address/port using cluster-announce-ip
and cluster-announce-port
. This is useful for Docker and NAT'ed setups. Furthermore, you can "hide" your Redis Cluster nodes behind any other proxy like stunnel
. A Redis Cluster node will announce the specified port/IP which can map to stunnel
, and you get an SSL-protected Redis Cluster. Please note that cluster-announce-ip
is not part of Redis 3.2 but will be released in future versions.
Redis Cluster SSL works pretty much the same as Redis Standalone with SSL. You can configure SSL and other SSL/TLS options using RedisURI
.
RedisURI redisURI = RedisURI.Builder.redis(host(), 7443)
.withSsl(true)
.withVerifyPeer(false)
.build();
RedisClusterClient redisClusterClient = RedisClusterClient.create(redisURI);
RedisConnection<String, String> connection = redisClusterClient.connect();
You should disable the verifyPeer
option if the SSL endpoints cannot provide a valid certificate. When creating a RedisClusterClient
using RedisClusterClientFactoryBean
the verifyPeer
option is disabled by default.
Lettuce was successfully tested with Azure Redis with SSL and authentication.
Read more: https://github.com/mp911de/lettuce/wiki/Redis-Cluster-%284.0%29
Redis Modules
Redis module support is a very young feature. lettuce provides a custom command API to dispatch own commands.
lettuce provides with 3.4.0 dispatch(…)
methods on the synchronous and asynchronous API type to provide a simple interface for command invocation.
RedisCodec<String, String> codec = new Utf8StringCodec();
String response = redis.dispatch(CommandType.SET,
new StatusOutput<>(codec),
new CommandArgs<>(codec)
.addKey(key)
.addValue(value));
Calls to dispatch(…)
on the synchronous API are blocking calls, calls on the asynchronous API return a RedisFuture<T>
.
Using dispatch(…)
allows to invoke arbitrary commands and works together within transactions and Redis Cluster. Exposing this API also allows choosing a different RedisCodec
for particular operations.
Read more: https://github.com/mp911de/lettuce/wiki/Custom-commands%2C-outputs-and-command-mechanics
If you need any support, meet lettuce at:
- Google Group: https://groups.google.com/d/forum/lettuce-redis-client-users
- Gitter: https://gitter.im/mp911de/lettuce
- Github Issues: https://github.com/mp911de/lettuce/issues
Commands
- Add support for CLUSTER BUMPEPOCH command #179
- Support extended MIGRATE syntax #197
- Add support for GEORADIUS STORE and STOREDIST options #199
- Add support for BITFIELD command #206
- Add support for SPOP key count #235
- Add support for GEOHASH command #239
- Add simple interface for custom command invocation for sync/async/reactive APIs #245
- Add support for variadic LPUSHX and RPUSHX #267
- Add support for TOUCH command #270
Enhancements
- Add log statement for resolved address #218 (Thanks to @mzapletal)
- Expose DNS Resolver #236
- Make latencyutils and commons-pool2 dependencies optional #237
- Support Redis Cluster with SSL #268
Fixes
- Lettuce fails sometimes at shutdown: DefaultClientResources.shutdown #194
- Extensive calls to PooledClusterConnectionProvider.closeStaleConnections #195
- Shared resources are closed altough still users are present #196
- Lettuce does not repackage new dependencies #198 (Thanks to @CodingFabian)
- Fix comparison for computationThreadPoolSize #205 (Thanks to @danhyun)
- Gracefully shutdown DefaultCommandLatencyCollector.PAUSE_DETECTOR #223 (Thanks to @sf-git and @johnou)
- RedisClient.connect(RedisURI) fails for unix socket based URIs #229 (Thanks to @nivekastoreth)
- HdrHistogram and LatencyUtils are not included in binary distribution #231
- Cache update in Partitions is not thread-safe #234
- GEORADIUSBYMEMBER, GEORADIUS and GEOPOS run into NPE when using Redis Transactions #241
- LettuceFutures.awaitAll throws RedisCommandInterruptedException when awaiting failed commands #242
- Perform multiple connection attempts when connecting a Redis Cluster #244
- Fix command sequence on connection activation #253 (Thanks to @long-xuan-nguyen)
- Cluster topology refresh: Failed connections are not closed bug #255
- Connection lifecycle state DISCONNECTED is considered a connected sate #257
- Writing commands while a disconnect is in progress leads to a race-condition #258
- Canceled commands lead to connection desynchronization #262 (Thanks to @long-xuan-nguyen)
- Fix JavaDoc for blocking list commands #272
- Unschedule topology refresh on cluster client shutdown #276
- Record command upon write #277
- Disable ConnectionWatchdog when closing a disconnected connection #278
- Perform selective relocation of org.* packages #280
- Guard key parameters against null values #287
- Guard command encoding against null #291 (Thanks to @christophstrobl)
Other
- Switch remaining tests to AssertJ #13
- Switch travis-ci to container build #203
- Code cleanups #215
- Upgrade to stunnel 5.33 #290
- Upgrade netty to 4.0.37.Final #294
- Upgrade rxjava to 1.1.6 #295
lettuce requires a minimum of Java 8 to build and Java 6 run. It is tested continuously against the unstable branch.
Javadoc: http://redis.paluch.biz/docs/api/releases/3.5.0.Final/
4.2.0.Final
That's the zero behind 4.2? Well, that's to not break OSGi support. Now let's talk about the more interesting things. Lettuce 4.2.0 is a major release and completes development of several notable enhancements.
This release comes with SSL support, Publish/Subscribe and adaptive topology refreshing for Redis Cluster. It features a major refactoring of the command handling and several improvements for Cloud-based Redis services and improvements to the Master/Slave API.
The usage of Guava was reduced for the most parts. Only the LoadingCache
, InetAddresses
and HostAndPort
components are still in use. A future lettuce 5.0 version will eliminate the use of Guava completely.
Important note for users of connection-pooling and latency tracking
Dependencies were streamlined with this release. Apache's commons-pool2
and latencyutils
are now optional dependencies. If you use connection-pooling or latency tracking, please include these dependencies explicitly otherwise these features will be disabled.
Lettuce 4.2.0 was verified with several Cloud-based Redis services. It works with different AWS ElastiCache usage patterns and is known to work with the Azure Redis Cluster service supporting SSL and authentication (see below).
lettuce 4.2.0 is fully binary compatible with the last release and can be used as a drop-in replacement for 4.1.x. This update is strongly recommended for lettuce 4.x users as it fixes some critical connection synchronization bugs.
Thanks to all contributors that made lettuce 4.2.0 possible.
lettuce 4.2.0 requires Java 8 and cannot be used with Java 6 or 7.
Redis Cluster Publish/Subscribe
Redis Cluster provides Publish/Subscribe features to broadcast messages across the cluster.
Using the standalone client allows using Publish/Subscribe with Redis Cluster but comes with the limitation of high-availability/failover.
If a node goes down, the connection is lost until the node is available again. lettuce addresses this issue with Redis Cluster Publish/Subscribe and provides a failover mechanism.
Publish/Subscribe messages and subscriptions are operated on the default cluster connection. The default connection is established with the node with the least client connections to achieve a homogeneous connection distribution. It also uses the cluster topology to failover if the currently connected node is down.
Publishing a message using the regular cluster connection is still possible (since 4.0). The regular cluster connection calculates a slot-hash from the channel (which is the key in this case). Publishing always connects to the master node which is responsible for the slot although PUBLISH
is not affected by the keyspace/slot-hash rule.
Read more: https://github.com/mp911de/lettuce/wiki/Pub-Sub-%284.0%29
Redis Cluster and SSL
Redis introduces an option to announce a specific IP address/port using cluster-announce-ip
and cluster-announce-port
. This is useful for Docker and NAT'ed setups. Furthermore, you can "hide" your Redis Cluster nodes behind any other proxy like stunnel
. A Redis Cluster node will announce the specified port/IP which can map to stunnel
, and you get an SSL-protected Redis Cluster. Please note that cluster-announce-ip
is not part of Redis 3.2 but will be released in future versions.
Redis Cluster SSL works pretty much the same as Redis Standalone with SSL. You can configure SSL and other SSL/TLS options using RedisURI
.
RedisURI redisURI = RedisURI.Builder.redis(host(), 7443)
.withSsl(true)
.withVerifyPeer(false)
.build();
RedisClusterClient redisClusterClient = RedisClusterClient.create(redisURI);
StatefulRedisClusterConnection<String, String> connection = redisClusterClient.connect();
You should disable the verifyPeer
option if the SSL endpoints cannot provide a valid certificate. When creating a RedisClusterClient
using RedisClusterClientFactoryBean
the verifyPeer
option is disabled by default.
Lettuce was successfully tested with Azure Redis with SSL and authentication.
Read more: https://github.com/mp911de/lettuce/wiki/Redis-Cluster-%284.0%29
Redis Cluster Topology Discovery and Refreshing
The lettuce Redis Cluster Client allows regular topology updates. lettuce 4.2.0 improves the existing topology updates with adaptive refreshing and dynamic/static topology discovery.
Adaptive refresh initiates topology view updates based on events happened during Redis Cluster operations. Adaptive triggers lead to an immediate topology refresh. Adaptive updates are rate-limited using a timeout since events can happen on a large scale. Adaptive refresh triggers are disabled by default and
can be enabled selectively:
MOVED_REDIRECT
ASK_REDIRECT
PERSISTENT_RECONNECTS
Dynamic/static topology discovery sources are the second change to topology refresh. lettuce uses by default dynamic discovery. Dynamic discovery retrieves the initial topology from the seed nodes and determines additional nodes to request their topology view. That is to reduce split-brain views by choosing the view which is shared by the majority of cluster nodes.
Dynamic topology discovery also provides latency data and client count for each node in the cluster. These details are useful for calculating the nearest node or the least used node.
Dynamic topology discovery can get expensive when running large Redis Clusters as all nodes from the topology are queried for their view. Static topology refresh sources limit the nodes to the initial seed node set. Limiting nodes is friendly to large clusters but it will provide latency and client count only for the seed nodes.
Read more: https://github.com/mp911de/lettuce/wiki/Client-options#adaptive-cluster-topology-refresh
Redis Modules
Redis module support is a very young feature. lettuce provides a custom command API to dispatch own commands. StatefulConnection
already allows sending of commands but requires wrapping of commands into the appropriate synchronization wrapper (Future, Reactive, Fire+Forget).
lettuce provides with 4.2.0 dispatch(…)
methods on each API type to provide a simpler interface.
RedisCodec<String, String> codec = new Utf8StringCodec();
String response = redis.dispatch(CommandType.SET,
new StatusOutput<>(codec),
new CommandArgs<>(codec)
.addKey(key)
.addValue(value));
Calls to dispatch(…)
on the synchronous API are blocking calls, calls on the asynchronous API return a RedisFuture<T>
and calls on the Reactive API return an Observable<T>
which flat-maps collection responses.
Using dispatch(…)
allows to invoke arbitrary commands and works together within transactions and Redis Cluster. Exposing this API also allows choosing a different RedisCodec
for particular operations.
Read more: https://github.com/mp911de/lettuce/wiki/Custom-commands%2C-outputs-and-command-mechanics
CommandHandler refactoring
Command sending, buffering, encoding and receiving was refactored on a large scale. Command encoding is performed in a separate handler and outside of CommandHandler
. It does not longer allocate an additional buffer to encode its arguments, but arguments are directly written to the command buffer that is used to encode single command/batch of commands. Fewer memory allocations help improving performance and do not duplicate data.
Synchronization and locking were reworked as well. The critical path used for writing commands is no longer locked exclusively but uses a shared locking with almost lock-free synchronization.
Improvements to Master/Slave connections
lettuce introduced with 4.1 a Master/Slave API which is now more dynamic. It's no longer required to connect to a Master node when using Master/Slave without Sentinel as the Master/Slave API will discover the master by itself. Providing one seed node enables dynamic lookup. The API is internally prepared for dynamic updates which are used with Redis Sentinel.
A Sentinel-managed Master/Slave setup discovers configuration changes based on Sentinel events and updates its topology accordingly.
Another change is the broader support of AWS ElastiCache Master/Slave setups. AWS ElastiCache allows various patterns for usage. One of them is the automatic failover. AWS ElastiCache exposes a connection point hostname and updates the DNS record to point to the current master node. Since the JVM has a built-in cache it's not trivial to adjust the DNS lookup and caching to the special needs which are valid only for AWS ElastiCache connections. lettuce exposes a DNS Lookup API that defaults to the JVM lookup. Lettuce ships also with DirContextDnsResolver
that allows own DNS lookups using either the system-configured DNS or external DNS servers. This implementation comes without caching and is suitable for AWS ElastiCache.
Another pattern is using AWS ElastiCache slaves. Before 4.2.0, a static setup was required. Clients had to point to the appropriate node. The Master/Slave API allows specifying a set of nodes which form a static Master/Slave setup. Lettuce discovers the roles from the provided nodes and routes read/write commands according to ReadFrom
settings.
Read more: https://github.com/mp911de/lettuce/wiki/Master-Slave
If you need any support, meet lettuce at:
- Google Group: https://groups.google.com/d/forum/lettuce-redis-client-users
- Gitter: https://gitter.im/mp911de/lettuce
- Github Issues: https://github.com/mp911de/lettuce/issues
Commands
- Add support for CLUSTER BUMPEPOCH command #179
- Support extended MIGRATE syntax #197
- Add support for GEORADIUS STORE and STOREDIST options #199
- Support SCAN in RedisCluster #201
- Add support for BITFIELD command #206
- Add zadd method accepting ScoredValue #210
- Add support for SPOP key count #235
- Add support for GEOHASH command #239
- Add simple interface for custom command ...
4.1.2.Final
lettuce 4.1.2 is a bugfix release.
Fixes
- Add log statement for resolved address #218 (Thanks to @mzapletal)
- Apply configured password/database number in MasterSlave connection #220
- Lazy initialization of PauseDetector and graceful shutdown #223 (Thanks to @sf-git)
- Fix RedisURI validation #229 (Thanks to @nivekastoreth)
- Add latencyutils and hdrhistogram to binary distribution #231
lettuce requires a minimum of Java 8 to build and run. It is tested continuously against the latest Redis source-build.
JavaDoc: http://redis.paluch.biz/docs/api/releases/4.1.2.Final/