{{announcement.body}}
{{announcement.title}}

Overview of Redisson: The Redis Java Client

DZone 's Guide to

Overview of Redisson: The Redis Java Client

Check out this comprehensive overview of Redisson!

· Java Zone ·
Free Resource

Java and Redisson

Check out this in-depth overview of Redisson!

Why Redisson?

Redis is an open-source, in-memory data structure store that can be used as a NoSQL key-value database, as well as a cache and message broker.

With lightning-fast speed, high availability and scalability, and support for a rich variety of data structures, it’s little wonder that developers are using Redis to build resilient and high-performance, non-relational databases.

According to a 2019 survey by programming Q&A website Stack Overflow, Redis is the “most loved” database technology, ahead of more established alternatives such as Oracle, MySQL, Microsoft SQL Server, and MongoDB.

You may also like: Distributed Java Collections in Redis With Redisson

Although Redis has a lot of features and benefits, users should be aware that Redis is not compatible with programming languages such as Java out-of-the-box. Rather, users who want to use Redis with Java need to use a third-party Java client library for Redis such as Redisson.

Redisson is a Redis client for Java that offers an in-memory data grid with support for many of the familiar Java collections, objects, and services. This rich feature set enables Java developers to quickly and easily get started with Redis, using the conventions that they are familiar with.

Redisson enables developers to focus less time on the programming aspect of Redis and devote more time to important concerns such as data modeling and application logic.

Based on the Netty asynchronous event-driven client-server framework, Redisson is compatible with Redis 2.8+ and JDK 1.8+. Redisson comes in two versions: the open-source Redisson project and Redisson PRO, which has greater speed and additional functionality.

This article will provide a comprehensive overview of everything you need to know about working with Redisson: configuring Redisson, Redis setup with Redisson, using Java objects and collections in Redis with Redisson, other Redisson features.

Maven Dependency

Large, complex Java projects often make use of build automation tools such as Apache Maven. If you use Maven to build your Java project, including support for Redisson is easy. Simply include the following lines in your pom.xml file:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.11.5</version>
</dependency>


This will provide the latest version of Redisson for your Java project (3.11.5 as of this writing). To make sure that you are using the most up-to-date Redisson version, check the Redisson project page on GitHub.

Gradle Dependency

Like Maven, Gradle is another open-source build automation tool for Java projects. Also like Maven, including support for Redisson in Gradle is extremely simple. Add the following line to your build.gradle file:

compile 'org.redisson:redisson:3.11.5'


Again, you can find the latest version of Redisson on the Redisson project page on GitHub.

Redis Setup

Naturally, the first step for using Redisson with Redis is to install Redis. You can find instructions for installing Redis on Linux and Mac OS X at the Redis Quick Start page. If you’re on a Windows machine, you can try using Microsoft’s unofficial port of Redis (although, note that this project is no longer actively maintained).

Once you’ve included the Redisson dependency via Maven or Gradle and installed Redis, the next step is to connect Redisson with Redis. Redisson supports connections to the following Redis configurations:

  • Single node
  • Master with slave nodes
  • Sentinel nodes
  • Clustered nodes
  • Replicated nodes

The following line of Java code connects to a single node instance of Redis:

RedissonClient client = Redisson.create();


After executing this line of code, the client is running on the default port 6379. You can change this port number, as well as other Redisson settings, by passing in arguments to the Redisson.create() method. This configuration can either be written directly in Java or loaded from an external file.

Configuring Redisson in Java

Below is an example of how to configure Redisson directly in Java:

Config config = new Config();
config.useSingleServer()
.setAddress("127.0.0.1:6379");
RedissonClient client = Redisson.create(config);


In this code, we first instantiate a Config object, and then, we can configure it to use the IP address 127.0.0.1 with port number 6379.

The useSingleServer() method indicates to Redis that we want to connect to a single node instance of Redis. The other options for connecting to different Redis configurations are:

Configuring Redisson From an External File

Alternatively, we can configure Redisson by loading settings from an external JSON or YAML file. Below is an example of loading Redisson settings from an external YAML file:

Config config = Config.fromYAML(new File("redisson.yaml"));  
RedissonClient client = Redisson.create(config);


The default Redisson settings within the corresponding YAML file are:

singleServerConfig:
    idleConnectionTimeout: 10000
    pingTimeout: 1000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    reconnectionTimeout: 3000
    failedAttempts: 3
    password: null
    subscriptionsPerConnection: 5
    clientName: null
    address: "redis://127.0.0.1:6379"
    subscriptionConnectionMinimumIdleSize: 1
    subscriptionConnectionPoolSize: 50
    connectionMinimumIdleSize: 10
    connectionPoolSize: 64
    database: 0
    dnsMonitoring: false
    dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.FstCodec> {}
useLinuxNativeEpoll: false


For detailed information about configuring Redisson, see the Configuration page on the Redisson wiki.

Redis-Based Java objects

Redisson includes support for a wide variety of Java objects. Individual instances of a Redisson object are serialized and stored in an available Redis node, or distributed in a cluster across multiple nodes.

The distributed Java objects in Redisson follow the specifications of the java.util.concurrent.atomic package. As such, you can perform lock-free, thread-safe, and atomic operations on the objects stored in Redis. Data remains consistent between different applications and servers.

In this section, we will discuss the different Java distributed objects in Redisson. For detailed information, consult the Distributed Objects page on the Redisson wiki.

ObjectHolder

The RBucket class in Redisson reimplements the ObjectHolder class in Java. An RBucket object is capable of holding any type of object. It has also Reactive and RxJava2 interfaces. Code example:

RBucket<Ledger> bucket = client.getBucket("ledger");
bucket.set(new Ledger());
Ledger ledger = bucket.get();


BinaryStreamHolder

The RBinaryStream interface in Redisson holds a binary stream. You can easily read from and write to the stream using the InputStream and OutputStream objects:

RBinaryStream stream = redisson.getBinaryStream("anyStream");
byte[] content = ...
stream.set(content);

InputStream is = stream.getInputStream();
byte[] readBuffer = new byte[512];
is.read(readBuffer);

OutputStream os = stream.getOuputStream();
byte[] contentToWrite = ...
os.write(contentToWrite);


GeospatialHolder

The RGeo interface in Redisson holds geospatial items. It has also Reactive and RxJava2 interfaces. Code example:

RGeo<String> geo = redisson.getGeo("test");
geo.add(new GeoEntry(13.361389, 38.115556, "Palermo"), 
new GeoEntry(15.087269, 37.502669, "Catania"));
geo.addAsync(37.618423, 55.751244, "Moscow");


BitSet

The RBitSet interface in Redisson represents a bit vector that can expand as necessary, with a maximum size of 4,294,967,295 bits. It has also Reactive and RxJava2 interfaces. Code example:

RBitSet set = redisson.getBitSet("simpleBitset");
set.set(0, true);
set.set(1812, false);
set.clear(0);


AtomicLong

The RAtomicLong interface in Redisson reimplements the AtomicLong class in Java, representing a long integer value that may be updated atomically. It has also Reactive and RxJava2 interfaces. Code example:

RAtomicLong atomicLong = client.getAtomicLong("myAtomicLong");
atomicLong.set(5);
atomicLong.incrementAndGet();


AtomicDouble

The RAtomicDouble interface in Redisson reimplements the AtomicDouble class in Java, representing a double value that may be updated atomically. It also has Reactive and RxJava2 interfaces. Code example:

RAtomicDouble atomicDouble = redisson.getAtomicDouble("myAtomicDouble");
atomicDouble.set(2.81);
atomicDouble.addAndGet(4.11);


Topic

The RTopic interface in Redisson is used to implement a publish/subscribe messaging system. Subscribers can listen for messages for a particular topic. It also has Reactive and RxJava2 interfaces. Code example:

RTopic topic = redisson.getTopic("anyTopic");
topic.addListener(SomeObject.class, new MessageListener<SomeObject>() {
    @Override
    public void onMessage(String channel, SomeObject message) {
        //...
    }
});


BloomFilter

The RBloomFilter interface in Redisson is used to implement the Bloom filter data structure:

RBloomFilter<SomeObject> bloomFilter = redisson.getBloomFilter("sample");
// initialize bloom filter with 
// expectedInsertions = 55000000
// falseProbability = 0.03
bloomFilter.tryInit(55000000L, 0.03);
bloomFilter.add(new SomeObject("field1Value", "field2Value"));
bloomFilter.add(new SomeObject("field5Value", "field8Value"));
bloomFilter.contains(new SomeObject("field1Value", "field8Value"));


HyperLogLog

The RHyperLogLog interface in Redisson provides access to the HyperLogLog algorithm and data structure implemented in Redis. HyperLogLog is used for estimating the number of unique elements in a multiset. It has also Reactive and RxJava2 interfaces. Code example:

RHyperLogLog<Integer> log = redisson.getHyperLogLog("log");
log.add(1);
log.add(2);
log.add(3);
log.count();


Redis-Based Java collections

Java collections in Redisson are handled the same way as objects. This allows you to perform lock-free, thread-safe, and atomic operations on the Java collections in Redisson.

The Java collections supported by Redisson are:

  • Map
  • Multimap
  • Set
  • SortedSet
  • ScoredSortedSet
  • LexSortedSet
  • List
  • Queue
  • Deque
  • BlockingQueue
  • BoundedBlockingQueue
  • BlockingDeque
  • BlockingFairQueue
  • DelayedQueue
  • PriorityQueue
  • PriorityDeque

For complete details about using these collections in Redisson, see the Distributed Collections page on the Redisson wiki.

Redis-Based Locks and Synchronizers

In Redisson, locks and synchronizers are distributed, allowing you to synchronize threads across multiple applications and servers. The Java locks and synchronizers supported by Redisson are:

  • Lock
  • FairLock
  • MultiLock
  • ReadWriteLock
  • Semaphore
  • PermitExpirableSemaphore
  • CountDownLatch

For complete details about using these collections in Redisson, see the Distributed Locks and Synchronizers page on the Redisson wiki.

Lock

The RLock interface in Redisson is a distributed implementation of the Lock interface in Java. It has also Reactive and RxJava2 interfaces. Code example:

RLock lock = client.getLock("lock");
lock.lock();
// perform some long operations...
lock.unlock();


MultiLock

The RedissonMultiLock class in Redisson allows users to manage multiple locks as a single unit:

RLock lock1 = clientInstance1.getLock("lock1");
RLock lock2 = clientInstance2.getLock("lock2");
RLock lock3 = clientInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
// perform long running operation...
lock.unlock();


Semaphore

The RSemaphore interface in Redisson is used to control access to a shared resource through the use of a counter. It has also Reactive, and RxJava2 interfaces. Code example:

RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
// or
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();

semaphore.releaseAsync();


Redis-Based services

Redisson includes support for five types of distributed services: Remote Service, Live Object Service, Executor Service, Scheduled Executor Service, and MapReduce Service. For a complete guide to distributed services in Redisson, consult the Distributed Services page on the Redisson wiki.

Remote Service

This service allows Redisson users to execute remote procedure calls in Java using the Async, Reactive, and RxJava2 APIs. It includes two aspects, the server-side implementation and the client-side implementation.

The server-side registers an interface for remote invocation:

RRemoteService remoteService = client.getRemoteService();
LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl();

remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);


The client-side calls a method of the registered remote interface:

RRemoteService remoteService = client.getRemoteService();
LedgerServiceInterface ledgerService
  = remoteService.get(LedgerServiceInterface.class);

List<String> entries = ledgerService.getEntries(10);


Live Object Service

“Live objects” in Redisson are an enhanced version of standard Java objects that can be shared between different machines and different JVMs. The fields of a live object are mapped to a Redis hash and can be accessed atomically, thanks to Redis’ single-threadedness.

The code below demonstrates the creation of a live object in Redis. The @RId annotation designates a unique or identifying field:

@REntity
public class LedgerLiveObject {
    @RId
    private String name;

    // getters and setters...
}


Once created, a live object can be used within an application and saved to Redis using the  persist() method:

RLiveObjectService service = client.getLiveObjectService();

LedgerLiveObject ledger = new LedgerLiveObject();
ledger.setName("ledger1");

ledger = service.persist(ledger);


Transactions

Transactions in Redis are atomic: either all of the commands in the transaction are processed, or none of them are. MULTIEXECDISCARD, and WATCH  are the four commands that are the foundation of Redis transactions. The MULTI command allows for multiple commands within a transaction, while the EXEC command executes all of the commands in the transaction.

Redisson supports executing transactions with the isolation level READ_COMMITTED using locks during write operations. The objects that are eligible for transactions in Redisson include RMapRMapCacheRLocalCachedMapRSetRSetCache, and RBucket.

The following code demonstrates the execution of a transaction in Redisson:

RTransaction transaction = redisson.createTransaction(TransactionOptions.defaults());

RMap<String, String> map = transaction.getMap("myMap");
map.put("1", "2");
String value = map.get("3");
RSet<String> set = transaction.getSet("mySet")
set.add(value);

try {
   transaction.commit();
} catch(TransactionException e) {
   transaction.rollback();
}


For more information, read the Transactions section on the Redisson wiki.

Pipelining

In Redis, pipelining is a feature that allows you to send multiple commands to the server in a batch as a single atomic operation, helping to reduce execution times. Pipelining is supported in Redisson with the RBatch class:

RBatch batch = client.createBatch();
batch.getMap("ledgerMap").fastPutAsync("1", "2");
batch.getMap("ledgerMap").putAsync("2", "5");
List<?> result = batch.execute();


Publish/subscribe

As discussed above, Redisson can be used to implement the publish/subscribe pattern (“pub/sub”) using the RTopic interface.

Below is an example of how to listen for published messages in Redisson:

RTopic subscribeTopic = client.getTopic("redisson");
subscribeTopic.addListener(CustomMessage.class, (channel, customMessage) 
           -> future.complete(customMessage.getMessage()));


subscribeTopic is an RTopic instance that listens for messages from the “redisson” channel. The  addListener() method specifies how to handle incoming messages from that channel.

The following code demonstrates how to publish messages to a channel (possibly from another application or server):

RTopic publishTopic = client.getTopic("redisson");
long clientsReceivedMessage = publishTopic.publish(new CustomMessage("Hello world"));


Integration With Frameworks

Redisson is fully compatible with popular Java frameworks including:

  • Spring Cache
  • Hibernate Cache
  • JCache
  • Tomcat Session Manager
  • Spring Session
  • Spring PlatformTransactionManager
  • Spring Boot starters
  • More than 20 statistics monitoring solutions (JMX, NewRelic, etc.)

For more information about using Java frameworks with Redisson, consult the Integration with Frameworks page on the Redisson wiki.

Redis Cluster support

Redis Cluster enables Redis users to automatically shard data across multiple Redis nodes, improving the database’s scalability and availability. Thanks to the distributed nature of Redisson’s Java constructs, Redis Cluster is easily compatible with Redisson.

The example below illustrates the usage of Redisson with Redis Cluster:

package redis.demo;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

public class Application 
{
    public static void main( String[] args )
    {
        Config config = new Config();
        config.useClusterServers()
              .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:6380");
        RedissonClient redisson = Redisson.create(config);
        // operations with Redis based Lock
        // implements java.util.concurrent.locks.Lock
        RLock lock = redisson.getLock("simpleLock");
        lock.lock();
        try {
           // do some actions
        } finally {
           lock.unlock();
        }
        // operations with Redis based Map
        // implements java.util.concurrent.ConcurrentMap
        RMap<String, String> map = redisson.getMap("simpleMap");
        map.put("mapKey", "This is a map value");
        String mapValue = map.get("mapKey");
        System.out.println("stored map value: " + mapValue);
        redisson.shutdown();
    }
}


Redis Sentinel support

Redis Sentinel is a high-availability solution for Redis that manages and monitors your Redis deployment. As with Redis Cluster, Redisson includes support for Redis Sentinel. You must specify at least one Redis Sentinel server and a master name when using Redisson with Redis Sentinel.

The example below illustrates the usage of Redisson with Redis Sentinel:

package redis.demo;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
/**
 * Redis Sentinel Java example
 *
 */
public class Application 
{
    public static void main( String[] args )
    {
        Config config = new Config();
        config.useSentinelServers()
              .addSentinelAddress("redis://127.0.0.1:6379")
              .setMasterName("myMaster");
        RedissonClient redisson = Redisson.create(config);
        // perform operations
        // implements java.util.concurrent.ConcurrentMap
        RMap<String, String> map = redisson.getMap("simpleMap");
        map.put("mapKey", "This is a map value");
        String mapValue = map.get("mapKey");
        System.out.println("stored map value: " + mapValue);
        // implements java.util.concurrent.locks.Lock
        RLock lock = redisson.getLock("simpleLock");
        lock.lock();
        try {
           // do some actions
        } finally {
           lock.unlock();
        }
        redisson.shutdown();
    }
}


Azure Cache, Amazon ElastiCache, and Google Cloud Memorystore Support

Redisson supports three of the most popular options for fully managed Redis services in the cloud:

  • Azure Cache
  • Amazon ElastiCache
  • Google Cloud Memorystore

To learn more about using Redisson with these Redis cloud services, consult our pages on Azure Cache and AWS ElastiCache.

Redisson Vs. Jedis

Redisson isn't the only Java client library for Redis. So how does Redisson compare with other Redis Java clients like Jedis?

For one, Redisson offers a much richer set of distributed collections than Jedis. The list of distributed collections in Redisson consists of:

  • Map
  • Multimap
  • Set
  • List
  • Queue
  • Deque
  • SortedSet
  • ScoredSortedSet
  • PriorityQueue
  • PriorityDeque
  • DelayedQueue
  • Stream
  • RingBuffer

Jedis, on the other hand, only supports the following distributed collections with plain commands:

  • Map
  • Multimap
  • Set
  • List
  • Queue
  • Deque
  • Stream
  • ScoredSortedSet

Distributed collections such as PriorityQueuesPriorityDequesDelayedQueuesStreams, and RingBuffers are not available in Jedis at all. In addition, Jedis does not support distributed locks and synchronizers such as LocksSemaphores, and CountDownLatches, or distributed services such as RemoteService and LiveObjectService.

Redisson also outperforms Jedis when it comes to features like advanced cache support, transactions, API architectures, and custom data serialization. To read a full comparison between Redisson and Jedis, check out our page Feature Comparison: Redisson vs. Jedis.

Further Reading

Distributed Java Collections in Redis With Redisson

Redis for Java Developers: Tutorials and Code Examples

Topics:
java ,redis

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}