redis/jedis
 Watch   
 Star   
 Fork   
2024-09-27 21:54:37
jedis

5.2.0 GA

Enhanced Client-side caching

We are happy to announce that improved server-assisted, client-side caching is now generally available! Special thanks to all our beta testers for their valuable feedback, which helped us refine and improve the initial implementation.

Client-side caching is supported exclusively with the RESP3 protocol with Redis >= 7.4 and is available in UnifiedJedis, JedisPooled, and JedisCluster and other classes.

How to try Client-Side Caching

  1. Install Jedis 5.2.0
  2. Use the following code example to get started:
public class CSCExampleTest {
  public static void main() {

    HostAndPort node = HostAndPort.from("localhost:6379");
    JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
        .resp3()                // RESP3 protocol is required for client-side caching
        //.user("myuser")       // Redis server username (optional)
        //.password("mypass")   // Redis user's password (optional)
        .build();

    CacheConfig cacheConfig = getCacheConfig();
    Cache cache = CacheFactory.getCache(cacheConfig);

    try (UnifiedJedis client = new UnifiedJedis(node, clientConfig, cache)) {
      client.set("foo", "bar");
      client.get("foo");
      client.get("foo"); // Cache hit

      System.out.println("Cache size: " + cache.getSize()); // 1
      System.out.println(cache.getStats().toString());

      //Let's change the value of "foo" to invalidate the value stored in the local cache
      client.mset("foo", "new_value", "ignore_me:1", "another_value");

      Thread.sleep(1000); // wait for the cache invalidation to happen

      System.out.println(client.get("foo")); // Cache miss
      System.out.println(cache.getStats().toString());

      client.get("ignore_me:1"); // Client will ignore this key

      System.out.println("Cache size: " + cache.getSize()); // still 1

      // check the cache stats
      System.out.println(cache.getStats().toString());

    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }

  private static CacheConfig getCacheConfig() {

    // This is a simple cacheable implementation that ignores keys starting with "ignore_me"
    Cacheable cacheable = new DefaultCacheable() {

      final String IGNORE_PREFIX = "ignore_me";

      @Override
      public boolean isCacheable(ProtocolCommand command, List<Object> keys) {
        // assuming we'll only execute methods with string keys
        List<String> stringKeys = keys.stream()
            .filter(obj -> obj instanceof String)
            .map(obj -> (String) obj)
            .collect(Collectors.toList());

        for (String key : stringKeys) {
          if (key.startsWith(IGNORE_PREFIX)) {
            return false;
          }
        }

        return isDefaultCacheableCommand(command);
      }
    };

    // Create a cache with a maximum size of 10000 entries
    return CacheConfig.builder()
        .maxSize(10000)
        .cacheable(cacheable)
        .build();
  }
}

It is possible to limit or ignore commands or keys for client-side caching. The getCacheConfig method presented above provides an example of how to achieve that.

🔥 Breaking Changes

  • JedisConnectionException contains HostAndPort from DefaultJedisSocketFactory (#3896)
  • Address change in JSON.GET command without path (#3858)
  • Modify and fail-fast GeoSearchParam (#3827)
  • Support transaction from UnifiedJedis without calling multi first (#3804)
  • Reduce the log level of validateObject to WARN (#3750)

🧪 Experimental Features

  • Support automatic namespacing (#3781)
  • Added support for ADDSCORES argument in FT.AGGREGATE (#3908)
  • Support IGNORE and other optional arguments for timeseries commands (#3860)

🚀 New Features

  • Support Hash field expiration (#3826)
  • Add equals and hashCode to Timeseries Params classes (#3959)
  • Decoding FT.SEARCH reply can be disabled at field level (#3926)
  • Get enriched Connection information (#3745)
  • Support execute the read-only command on replica nodes (#3848)
  • JedisConnectionException contains HostAndPort from DefaultJedisSocketFactory (#3896)
  • Support [S]PUBLISH in pipelines and transactions (#3859)
  • Support Hash field expiration (#3826)
  • Custom connection pool to MultiClusterPooledConnectionProvider (#3801)
  • PubSub handle array of messages for RESP2 (#3811)
  • Support transaction from UnifiedJedis without calling multi first (#3804)
  • Add last entry id for XREADs and support XREADs reply as map (#3791)
  • Add Experimental, Internal and VisibleForTesting annotations (#3790)
  • Implement equals and hashcode in Params classes (#3728)
  • Add support for redis command: CLIENT TRACKINGINFO (#3751)
  • Support the MAXAGE option for CLIENT KILL (#3754)
  • Polish #3741 (#3746)
  • Add support for the NOVALUES option of HSCAN (#3741)
  • Support issuing Latency commands (#3729)

🐛 Bug Fixes

  • Accept null replies for BZPOPMAX and BZPOPMIN commands (#3930)
  • Fix empty LUA table reply (#3924)
  • Ensure closing connection in Pipeline (#3865)
  • Address change in JSON.GET command without path (#3858)
  • Consider null values in empty StreamPendingSummary (#3793)
  • Fix UnifiedJedis pexpireAt glitch (#3782)
  • Use expiryOption in PipelineBase.expireAt (#3777)
  • Stop connection fetching before sync/exec (#3756)
  • Check for thread interrupt in subscribe process of PubSub (#3726)
  • Avoid NPE in MultiNodePipelineBase.java (#3697)
  • Fix probable missing (RESP3) protocol processing (#3692)
  • Use circuit breaker fallback exception list (#3664)

🧰 Maintenance

  • Deprecate Triggers and Functions feature (#3968)
  • Bump org.apache.httpcomponents.client5:httpclient5-fluent from 5.3.1 to 5.4 (#3962)
  • Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.1 to 3.5.0 (#3950)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0 (#3949)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.5 to 3.2.6 (#3957)
  • Added JavaDoc for basic JedisCluster constructors (#3304)
  • Bump org.locationtech.jts:jts-core from 1.19.0 to 1.20.0 (#3948)
  • Add A-A failover scenario test (#3935)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.4 to 3.2.5 (#3936)
  • Fix codecov upload (#3933)
  • Rename readonly config param to specify Redis Cluster (#3932)
  • Modify Connection.toIdentityString and test (#3931)
  • Revert "Creating CODEOWNERS for the examples (#3570)" (#3897)
  • Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.5 to 3.3.1 (#3891)
  • Bump org.hamcrest:hamcrest from 2.2 to 3.0 (#3914)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0 (#3909)
  • Bump net.javacrumbs.json-unit:json-unit from 2.38.0 to 2.40.1 (#3903)
  • Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.1 (#3890)
  • Fixed typo in Javadoc (#3917)
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.1 to 3.4.2 (#3910)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.9.1 to 2.10.0 (#3901)
  • Bump jackson.version from 2.17.1 to 2.17.2 (#3902)
  • Add Scenario tests (#3847)
  • Modify the judgment that reads a response as empty to isEmpty method (#3888)
  • Replace synchronized with j.u.c.l.ReentrantLock for Loom (#3480)
  • Extract messages of unsupported exception as constants (#3887)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0 (#3851)
  • Bump org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0 (#3850)
  • Bump com.google.code.gson:gson from 2.10.1 to 2.11.0 (#3842)
  • Merge doc tests into main branch to keep in-sync with the code (#3861)
  • Deprecate unused Set builders (#3857)
  • Disable Redis Graph tests (#3856)
  • Introduce EndpointConfig and load endpoint settings from the endpoints.json file (#3836)
  • Address Gears test fail - Cleanup Function libraries (#3840)
  • Bump jackson.version from 2.17.0 to 2.17.1 (#3833)
  • Add methods in CommandArguments and RawableFactory (#3834)
  • Modify and fail-fast GeoSearchParam (#3827)
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.0 to 3.4.1 (#3822)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.3 to 3.2.4 (#3823)
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.0 (#3819)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.3 (#3818)
  • Add more tests for the CommandObjects class (#3809)
  • Resolve compile warnings (#3810)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.9.0 to 2.9.1 (#3806)
  • Bump org.jacoco:jacoco-maven-plugin from 0.8.11 to 0.8.12 (#3805)
  • Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 (#3807)
  • Deprecate unused JSON.ARRAPPEND in CommandObjects (#3798)
  • Extensive unit tests for the CommandObjects class (#3796)
  • Add extensive tests for UnifiedJedis (#3788)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.1 to 3.2.2 (#3794)
  • Add Experimental, Internal and VisibleForTesting annotations (#3790)
  • Add TS.INFO [DEGUB] and CF.MEXISTS in pipelined commands (#3787)
  • Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0 (#3786)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.0 to 3.2.1 (#3785)
  • Pipelined tests for lists and sets, and API typo fix (#3772)
  • Extensive unit tests for PipeliningBase (#3778)
  • Bump jackson.version from 2.16.2 to 2.17.0 (#3776)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.0 (#3775)
  • Fix typo in SetPipelineCommands method name (#3773)
  • Streamline test execution (#3760)
  • Add pipelined tests for sorted sets (#3771)
  • Geo pipelined tests (#3767)
  • Reenable clustering tests (#3764)
  • GETSET command is deprecated since Redis 6.2.0 (#3768)
  • Add tests for Stream pipelined commands (#3763)
  • Bump jackson.version from 2.16.1 to 2.16.2 (#3762)
  • Bump org.json:json from 20240205 to 20240303 (#3752)
  • Add Hashes pipeline commands unit tests (#3288)
  • Add unit tests for pipelining - migrate and db commands (#3759)
  • Reduce the log level of validateObject to WARN (#3750)
  • Bump org.json:json from 20231013 to 20240205 (#3706)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.8.3 to 2.9.0 (#3724)
  • Running doctests also on emb-examples (#3693)
  • Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.3 to 3.2.5 (#3688)
  • Run integration workflow for 5.2.0 branch (#3681)
  • Bump jackson.version from 2.16.0 to 2.16.1 (#3666)
  • Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.12.1 (#3665)
  • Spellcheck as part of CI (#3492)
  • Adding stale issues workflow (#3528)
  • Creating CODEOWNERS for documentation (#3570)
  • Unifying GitHub tokens (#3650)
  • Replace deprecated set-output command with environment file (#3622)
  • Fixing GPG key usage (#3670)
  • Bump maven-surefire-plugin to 3.2.3 (#3656)
  • Bump org.jacoco:jacoco-maven-plugin from 0.8.5 to 0.8.11 (#3653)
  • Bump jackson databind and jsr310 to 2.16.0 (#3655)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3 (#3639)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.8.1 to 2.8.3 (#3647)
  • Access Reducer attributes (#3637)
  • Address RediSearch profile change (#3636)

Contributors

We'd like to thank all the contributors who worked on this release!

@Gandalf1783, @Lcarrot, @SoilChang, @andy-stark-redis, @ascdi, @babanin, @cemasma, @chayim, @dependabot, @dependabot[bot], @gerzse, @jjz921024, @jongwooo, @sazzad16, @stillerrr, @thachlp, @uglide, @vanta and @zyfx595701088

2024-08-29 22:57:31
jedis
2024-08-22 17:46:30
jedis

5.1.5

Changes

🐛 Bug Fixes

  • Accept null replies for BZPOPMAX and BZPOPMIN commands (#3930)
  • Fix empty LUA table reply (#3924)

Contributors

We'd like to thank all the contributors who worked on this release!

@JW-Vinay, @ngavrailov and @sazzad16

2024-07-29 19:06:52
jedis

5.1.4

Changes

🔥 Breaking Changes

  • Address change in JSON.GET command without path (#3858)
  • Modify and fail-fast GeoSearchParam (#3827)

🚀 New Features

  • Support Hash field expiration (#3826)
  • Support issuing Latency commands (#3729)
  • Add support for the NOVALUES option of HSCAN command (#3741, #3746)
  • Add support for CLIENT TRACKINGINFO command (#3751)
  • Support IGNORE and other optional arguments for timeseries commands (#3860, #3863)
  • Add last entry id for XREADs and support XREADs reply as map (#3791)
  • Support the MAXAGE option for CLIENT KILL (#3754)
  • Support ADDSCORES argument in FT.AGGREGATE (#3908)
  • Support [S]PUBLISH in pipelines and transactions (#3859)

🐛 Bug Fixes

  • Ensure closing connection in Pipeline (#3865)
  • Address change in JSON.GET command without path (#3858)

🧰 Maintenance

  • Add methods in CommandArguments and RawableFactory (#3834)
  • Modify and fail-fast GeoSearchParam (#3827)

Contributors

We'd like to thank all the contributors who worked on this release!

@sazzad16, @cemasma, @Lcarrot, @gerzse and @uglide

2024-06-11 00:32:26
jedis

5.2.0-beta4

What's new

Redis 7.4-RC1 support

In this release, we added support for Redis 7.4-RC1, including:

  • Support Hash field expiration (#3826)
  • Add last entry id for XREADs and support XREADs reply as map (#3791)
  • Add support for the NOVALUES option of HSCAN (#3741, #3746)
  • Support the MAXAGE option for CLIENT KILL (#3754)

Client-side caching

This release supports server-assisted, client-side caching, and is currently beta grade.

Client-side caching is available within UnifiedJedis, JedisPooled, JedisCluster, etc classes via implementation of ClientSideCache class, with only RESP3 protocol. It is recommended to use a ClientSideCache implementation with TTL (time-to-live). We have included two implementations based on Google Guava and Caffeine libraries.

How to try Client-Side Caching

  1. Install Jedis 5.2.0-beta3
  2. Choose and install a caching library: Google Guava or Caffeine
  3. Use the following code example to get started:
import redis.clients.jedis.*;
import redis.clients.jedis.csc.*;

class CacheExample {
    public static void main() {
        HostAndPort node = HostAndPort.from("localhost:6379");
        JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
                                            .resp3()                // RESP3 protocol
                                            //.user("myuser")       // Redis server username (optional)
                                            //.password("mypass")   // Redis user's password (optional)
                                            .build();

        ClientSideCache clientSideCache;
        // Uncomment one of the following lines to use the corresponding cache backend
        // GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().maximumSize(10_000).ttl(100).build();
        // CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().maximumSize(10_000).ttl(100).build();

        UnifiedJedis client = new UnifiedJedis(node, clientConfig, clientSideCache);
        // JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache);
        // JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache);

        client.set("foo", "bar");
        client.get("foo");
        client.get("foo");          // cache hit
        client.del("foo");

        client.close();
    }
}

It is highly recommended to use a ClientSideCache implementation with TTL. Both of our provided GuavaClientSideCache and CaffeineClientSideCache have TTL support and use a default value when not set. It is discouraged to use ttl(0) in these.

It is also a good idea to keep the idle connections busy to get more and updated notifications. It can be done easily using pool config:

GenericObjectPoolConfig<Connection> poolConfig = new ConnectionPoolConfig();
poolConfig.setTestWhileIdle(true);              // ConnectionPoolConfig by default does this.
                                                // It is still shown here for better understanding.

This pool config can be used as follows:

JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache, poolConfig);
JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache, poolConfig);

It is possible to limit or ignore commands and/or keys for client side caching. For example, if we want to ignore some keys based on their prefix, we can define a ClientSideCacheable:

final String IGNORE_PREFIX = "PREFIX_TO_IGNORE";
ClientSideCacheable isCacheable = new ClientSideCacheable() {
    @Override
    public boolean isCacheable(ProtocolCommand command, Object... keys) {
        for (String key : (String[]) keys) { // assuming we'll only execute methods with String keys
            if (key.startsWith(IGNORE_PREFIX)) {
                return false;
            }
        }
        return true;
    }
};

This ClientSideCacheable can be a parameter for ClientSideCache. In our provided implementations, it can be:

GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().cacheable(isCacheable).build();
CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().cacheable(isCacheable).build();

It is also possible to create client-side caching enabled client object using URL/URI with proper query params. Supported params are:

  • cache_lib (caching library) - required; can be either guava or caffeine
  • cache_max_size (maximum no of commands) - optional
  • cache_ttl (time-to-live, in seconds) - optional

For example:

JedisPooled client = new JedisPooled("redis://myuser:mypass@localhost:6379/?cache_lib=guava&cache_max_size=10000&cache_ttl=100");

🔥 Breaking Changes

  • Address change in JSON.GET command without path (#3858)
  • Modify and fail-fast GeoSearchParam (#3827)
  • Support transaction from UnifiedJedis without calling multi first (#3804)
  • Reduce the log level of validateObject to WARN (#3750)

🚀 Other notable improvements

  • Support [S]PUBLISH commands in pipelines and transactions (#3859)
  • PubSub handle array of messages for RESP2 (#3811)
  • Add Experimental, Internal and VisibleForTesting annotations (#3790)
  • Implement equals and hashcode in Params classes (#3728)
  • Support CLIENT TRACKINGINFO command (#3751)
  • Support issuing Latency commands (#3729)

🧰 Maintenance

  • Bump org.json:json from 20231013 to 20240303 (#3706, #3752)
  • Access Reducer attributes (#3637)
  • Add methods in CommandArguments and RawableFactory (#3834)
  • Deprecate unused Set builders (#3857)
  • Deprecate unused JSON.ARRAPPEND in CommandObjects (#3798)
  • GETSET command is deprecated since Redis 6.2.0 (#3768)
  • Resolve compile warnings (#3810)
  • Disable Redis Graph tests (#3856)
  • Introduce EndpointConfig and load endpoint settings from the endpoints.json file (#3836)
  • Address Gears test fail - Cleanup Function libraries (#3840)
  • Add more tests for the CommandObjects class (#3809)
  • Extensive unit tests for the CommandObjects class (#3796)
  • Add extensive tests for UnifiedJedis (#3788)
  • Pipelined tests for lists and sets, and API typo fix (#3772)
  • Extensive unit tests for PipeliningBase (#3778)
  • Streamline test execution (#3760)
  • Add pipelined tests for sorted sets (#3771)
  • Geo pipelined tests (#3767)
  • Reenable clustering tests (#3764)
  • Add tests for Stream pipelined commands (#3763)
  • Add Hashes pipeline commands unit tests (#3288)
  • Add unit tests for pipelining - migrate and db commands (#3759)
  • Address RediSearch profile change (#3636)
  • Running doctests also on emb-examples (#3693)
  • Run integration workflow for 5.2.0 branch (#3681)
  • Spellcheck as part of CI (#3492)
  • Adding stale issues workflow (#3528)
  • Creating CODEOWNERS for documentation (#3570)
  • Unifying GitHub tokens (#3650)
  • Replace deprecated set-output command with environment file (#3622)
  • Fixing GPG key usage (#3670)
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.1 (#3819, #3822)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.4 (#3775, #3785, #3794, #3818, #3823)
  • Bump org.jacoco:jacoco-maven-plugin from 0.8.5 to 0.8.12 (#3653, #3805)
  • Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 (#3807)
  • Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.13.0 (#3665, #3786)
  • Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.2 to 3.2.5 (#3656, #3688)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3 (#3639)
  • Bump jackson.version (com.fasterxml.jackson.core:jackson-databind and com.fasterxml.jackson.datatype:jackson-datatype-jsr310) from 2.14.2 to 2.17.1 (#3666, #3762, #3776, #3833)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.8.1 to 2.9.1 (#3647, #3724, #3806)

Contributors

We'd like to thank all the contributors who worked on this release!

@Lcarrot, @cemasma, @chayim, @gerzse, @sazzad16 and @uglide

2024-06-07 02:59:48
jedis

5.2.0-beta3

What's new

Redis 7.4-RC1 support

In this release, we added support for Redis 7.4-RC1, including:

  • Support Hash field expiration (#3826)
  • Add last entry id for XREADs and support XREADs reply as map (#3791)
  • Add support for the NOVALUES option of HSCAN (#3741, #3746)
  • Support the MAXAGE option for CLIENT KILL (#3754)

Client-side caching

This release supports server-assisted, client-side caching, and is currently beta grade.

Client-side caching is available within UnifiedJedis, JedisPooled, JedisCluster, etc classes via implementation of ClientSideCache class, with only RESP3 protocol. It is recommended to use a ClientSideCache implementation with TTL (time-to-live). We have included two implementations based on Google Guava and Caffeine libraries.

How to try Client-Side Caching

  1. Install Jedis 5.2.0-beta3
  2. Choose and install a caching library: Google Guava or Caffeine
  3. Use the following code example to get started:
import redis.clients.jedis.*;
import redis.clients.jedis.csc.*;

class CacheExample {
    public static void main() {
        HostAndPort node = HostAndPort.from("localhost:6379");
        JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
                                            .resp3()                // RESP3 protocol
                                            //.user("myuser")       // Redis server username (optional)
                                            //.password("mypass")   // Redis user's password (optional)
                                            .build();

        ClientSideCache clientSideCache;
        // Uncomment one of the following lines to use the corresponding cache backend
        // GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().maximumSize(10_000).ttl(100).build();
        // CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().maximumSize(10_000).ttl(100).build();

        UnifiedJedis client = new UnifiedJedis(node, clientConfig, clientSideCache);
        // JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache);
        // JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache);

        client.set("foo", "bar");
        client.get("foo");
        client.get("foo");          // cache hit
        client.del("foo");

        client.close();
    }
}

It is highly recommended to use a ClientSideCache implementation with TTL. Both of our provided GuavaClientSideCache and CaffeineClientSideCache have TTL support and use a default value when not set. It is discouraged to use ttl(0) in these.

It is also a good idea to keep the idle connections busy to get more and updated notifications. It can be done easily using pool config:

GenericObjectPoolConfig<Connection> poolConfig = new ConnectionPoolConfig();
poolConfig.setTestWhileIdle(true);              // ConnectionPoolConfig by default does this.
                                                // It is still shown here for better understanding.

This pool config can be used as follows:

JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache, poolConfig);
JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache, poolConfig);

It is possible to limit or ignore commands and/or keys for client side caching. For example, if we want to ignore some keys based on their prefix, we can define a ClientSideCacheable:

final String IGNORE_PREFIX = "PREFIX_TO_IGNORE";
ClientSideCacheable isCacheable = new ClientSideCacheable() {
    @Override
    public boolean isCacheable(ProtocolCommand command, Object... keys) {
        for (String key : (String[]) keys) { // assuming we'll only execute methods with String keys
            if (key.startsWith(IGNORE_PREFIX)) {
                return false;
            }
        }
        return true;
    }
};

This ClientSideCacheable can be a parameter for ClientSideCache. In our provided implementations, it can be:

GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().cacheable(isCacheable).build();
CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().cacheable(isCacheable).build();

It is also possible to create client-side caching enabled client object using URL/URI with proper query params. Supported params are:

  • cache_lib (caching library) - required; can be either guava or caffeine
  • cache_max_size (maximum no of commands) - optional
  • cache_ttl (time-to-live, in seconds) - optional

For example:

JedisPooled client = new JedisPooled("redis://myuser:mypass@localhost:6379/?cache_lib=guava&cache_max_size=10000&cache_ttl=100");

🔥 Breaking Changes

  • Modify and fail-fast GeoSearchParam (#3827)
  • Support transaction from UnifiedJedis without calling multi first (#3804)
  • Reduce the log level of validateObject to WARN (#3750)

🚀 Other notable improvements

  • PubSub handle array of messages for RESP2 (#3811)
  • Support transaction from UnifiedJedis without calling multi first (#3804)
  • Add Experimental, Internal and VisibleForTesting annotations (#3790)
  • Implement equals and hashcode in Params classes (#3728)
  • Add support for redis command: CLIENT TRACKINGINFO (#3751)
  • Support issuing Latency commands (#3729)

🧰 Maintenance

  • Bump org.json:json from 20231013 to 20240303 (#3706, #3752)
  • Access Reducer attributes (#3637)
  • Add methods in CommandArguments and RawableFactory (#3834)
  • Deprecate unused JSON.ARRAPPEND in CommandObjects (#3798)
  • GETSET command is deprecated since Redis 6.2.0 (#3768)
  • Introduce EndpointConfig and load endpoint settings from the endpoints.json file (#3836)
  • Address Gears test fail - Cleanup Function libraries (#3840)
  • Add more tests for the CommandObjects class (#3809)
  • Resolve compile warnings (#3810)
  • Extensive unit tests for the CommandObjects class (#3796)
  • Add extensive tests for UnifiedJedis (#3788)
  • Pipelined tests for lists and sets, and API typo fix (#3772)
  • Extensive unit tests for PipeliningBase (#3778)
  • Streamline test execution (#3760)
  • Add pipelined tests for sorted sets (#3771)
  • Geo pipelined tests (#3767)
  • Reenable clustering tests (#3764)
  • Add tests for Stream pipelined commands (#3763)
  • Add Hashes pipeline commands unit tests (#3288)
  • Add unit tests for pipelining - migrate and db commands (#3759)
  • Running doctests also on emb-examples (#3693)
  • Run integration workflow for 5.2.0 branch (#3681)
  • Spellcheck as part of CI (#3492)
  • Adding stale issues workflow (#3528)
  • Creating CODEOWNERS for documentation (#3570)
  • Unifying GitHub tokens (#3650)
  • Replace deprecated set-output command with environment file (#3622)
  • Fixing GPG key usage (#3670)
  • Address RediSearch profile change (#3636)
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.1 (#3819, #3822)
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.4 (#3775, #3785, #3794, #3818, #3823)
  • Bump org.jacoco:jacoco-maven-plugin from 0.8.5 to 0.8.12 (#3653, #3805)
  • Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 (#3807)
  • Bump org.apache.maven.plugins:maven-compiler-plugin from 3.11.0 to 3.13.0 (#3665, #3786)
  • Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.2 to 3.2.5 (#3656, #3688)
  • Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3 (#3639)
  • Bump jackson.version (com.fasterxml.jackson.core:jackson-databind and com.fasterxml.jackson.datatype:jackson-datatype-jsr310) from 2.14.2 to 2.17.1 (#3666, #3762, #3776, #3833)
  • Bump com.kohlschutter.junixsocket:junixsocket-core from 2.8.1 to 2.9.1 (#3647, #3724, #3806)

Contributors

We'd like to thank all the contributors who worked on this release!

@Lcarrot, @cemasma, @chayim, @gerzse, @sazzad16 and @uglide

2024-05-20 20:02:12
jedis

5.1.3

Changes

🚀 New Features

  • Custom connection pool to MultiClusterPooledConnectionProvider (#3801)

🐛 Bug Fixes

  • Consider null values in empty StreamPendingSummary (#3793)
  • Fix UnifiedJedis pexpireAt glitch (#3782)
  • Use expiryOption in PipelineBase.expireAt (#3777)

🧰 Maintenance

  • Add TS.INFO [DEGUB] and CF.MEXISTS in pipelined commands (#3787)
  • Fix typo in SetPipelineCommands method name (#3773)
  • Bump jackson.version from 2.16.1 to 2.16.2 (#3762)

Contributors

We'd like to thank all the contributors who worked on this release!

@gerzse, @sazzad16, @thachlp and @jarkus4

2024-05-07 18:04:35
jedis

5.2.0-beta2

What's new

This release supports server-assisted, client-side caching, and is currently beta grade.

Client-side caching is available within UnifiedJedis, JedisPooled, JedisCluster, etc classes via implementation of ClientSideCache class, with only RESP3 protocol. It is recommended to use a ClientSideCache implementation with TTL (time-to-live). We have included two implementations based on Google Guava and Caffeine libraries.

How to try Client-Side Caching

  1. Install Jedis 5.2.0-beta2
  2. Choose and install a caching library: Google Guava or Caffeine
  3. Use the following code example to get started:
import redis.clients.jedis.*;
import redis.clients.jedis.csc.*;

class CacheExample {
    public static void main() {
        HostAndPort node = HostAndPort.from("localhost:6379");
        JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
                                            .resp3()                // RESP3 protocol
                                            //.user("myuser")       // Redis server username (optional)
                                            //.password("mypass")   // Redis user's password (optional)
                                            .build();

        ClientSideCache clientSideCache;
        // Uncomment one of the following lines to use the corresponding cache backend
        // GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().maximumSize(10_000).ttl(100).build();
        // CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().maximumSize(10_000).ttl(100).build();

        UnifiedJedis client = new UnifiedJedis(node, clientConfig, clientSideCache);
        // JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache);
        // JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache);

        client.set("foo", "bar");
        client.get("foo");
        client.get("foo");          // cache hit
        client.del("foo");

        client.close();
    }
}

It is highly recommended to use a ClientSideCache implementation with TTL. Both of our provided GuavaClientSideCache and CaffeineClientSideCache have TTL support and use a default value when not set. It is discouraged to use ttl(0) in these.

It is also a good idea to keep the idle connections busy to get more and updated notifications. It can be done easily using pool config:

GenericObjectPoolConfig<Connection> poolConfig = new ConnectionPoolConfig();
poolConfig.setTestWhileIdle(true);              // ConnectionPoolConfig by default does this.
                                                // It is still shown here for better understanding.

This pool config can be used as follows:

JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache, poolConfig);
JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache, poolConfig);

It is possible to limit or ignore commands and/or keys for client side caching. For example, if we want to ignore some keys based on their prefix, we can define a ClientSideCacheable:

final String IGNORE_PREFIX = "PREFIX_TO_IGNORE";
ClientSideCacheable isCacheable = new ClientSideCacheable() {
    @Override
    public boolean isCacheable(ProtocolCommand command, Object... keys) {
        for (String key : (String[]) keys) { // assuming we'll only execute methods with String keys
            if (key.startsWith(IGNORE_PREFIX)) {
                return false;
            }
        }
        return true;
    }
};

This ClientSideCacheable can be a parameter for ClientSideCache. In our provided implementations, it can be:

GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().cacheable(isCacheable).build();
CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().cacheable(isCacheable).build();

It is also possible to create client-side caching enabled client object using URL/URI with proper query params. Supported params are:

  • cache_lib (caching library) - required; can be either guava or caffeine
  • cache_max_size (maximum no of commands) - optional
  • cache_ttl (time-to-live, in seconds) - optional

For example:

JedisPooled client = new JedisPooled("redis://myuser:mypass@localhost:6379/?cache_lib=guava&cache_max_size=10000&cache_ttl=100");
2024-04-04 15:51:42
jedis

4.4.8

Changes

🐛 Bug Fixes

  • Fix ZREVRANGE versions with max/min swapped in MultiNodePipelineBase (#3784)
  • Use expiryOption in PipelineBase.expireAt (#3777)
  • Fix UnifiedJedis pexpireAt glitch (#3782)
  • Consider null values in empty StreamPendingSummary (#3793)

Contributors

We'd like to thank all the contributors who worked on this release!

@sazzad16 and @keeferrourke

2024-03-11 02:58:39
jedis

5.2.0-beta1

This release provides support for server-assisted, client-side caching, and is currently beta grade.

Client-side caching is available within UnifiedJedis, JedisPooled, JedisCluster, etc classes via implementation of ClientSideCache class, with RESP3 only. It is recommended a ClientSideCache implementation with TTL (time-to-live). We have included two implementations based on Google Guava and Caffeine libraries.

class CacheExample {
    public static void main() {
        HostAndPort node = HostAndPort.from("localhost:6379");
        JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
                                            .resp3()                        // RESP3 protocol
                                            .password("foobared")
                                            .build();

        ClientSideCache clientSideCache;
        // GuavaClientSideCache clientSideCache = GuavaClientSideCache.builder().maximumSize(1000).ttl(100).build();
        // CaffeineClientSideCache clientSideCache = CaffeineClientSideCache.builder().maximumSize(1000).ttl(100).build();

        UnifiedJedis client = new UnifiedJedis(node, clientConfig, clientSideCache);
        // JedisPooled client = new JedisPooled(node, clientConfig, clientSideCache);
        // JedisCluster client = new JedisCluster(Collections.singleton(node), clientConfig, clientSideCache);

        client.set("foo", "bar");
        client.get("foo");
        client.get("foo");          // cache hit
        client.del("foo");

        client.close();
    }
}