Learnitweb

Working with Redis Increment and Decrement Commands using Redisson

In this section, we will explore how to work with increment and decrement operations in Redis using the Redisson Java client library.

Until now, we have mostly been storing simple string values or Java objects in Redis. But Redis also supports numeric operations, allowing us to increment or decrement numeric values directly on the server — which is much faster and atomic.

Let’s see how this is done in Redisson.


Step 1: Create a New Test Class

We’ll begin by creating a new class, for example:

public class NumberTest extends TestBase {
}

This class will contain a test method where we will explore Redis increment/decrement functionality.

Inside this class, let’s define a test method:

@Test
public void valueIncreaseTest() {
    // logic will go here
}

Step 2: Understanding Redis Commands

In plain Redis, if we want to increment a number, we can use the following command:

INCR key

Similarly, to decrement a number:

DECR key

However, these commands only work if the stored value is numeric.
If you try to use INCR on a string value (for example "hello"), Redis will throw an error saying it cannot perform arithmetic operations on non-numeric values.


Step 3: Limitations of RBucket

In Redisson, we have been using the RBucket object to store and retrieve simple key-value pairs.

RBucket<String> bucket = redisson.getBucket("sampleKey");
bucket.set("value");

But if you check the available methods on RBucket, you’ll notice that it does not provide increment or decrement methods such as incrementAndGet() or decrementAndGet().
That’s because RBucket is a generic abstraction for storing any kind of value — strings, objects, or other data types.

To handle numeric operations efficiently, Redisson provides specialized classes.


Step 4: Using AtomicLong and AtomicDouble

Redisson offers data structures similar to Java’s AtomicLong and AtomicDouble.
These are:

  • RAtomicLong
  • RAtomicDouble

They provide atomic numeric operations like increment, decrement, and get/set, all directly synchronized with Redis.

For our example, we’ll use RAtomicLong.

RAtomicLong counter = redisson.getAtomicLong("user:visit:count");

Now, you can perform operations like:

counter.incrementAndGet();
counter.decrementAndGet();

This is conceptually similar to Java’s AtomicLong, except the value is persisted and shared across all Redis clients.


Step 5: Implementing a Reactive Test

Let’s simulate a case where the value increases periodically — say, once every second for 30 seconds.
We can use Reactor’s Flux to achieve this in a reactive style.

@Test
public void valueIncreaseTest() {
    RAtomicLong counter = redisson.getAtomicLong("user:visit:count");
    counter.set(0);

    Flux.range(1, 30)
        .delayElements(Duration.ofSeconds(1))
        .doOnNext(i -> counter.incrementAndGet())
        .doOnComplete(() -> System.out.println("Increment complete"))
        .subscribe();

    StepVerifier.create(Mono.delay(Duration.ofSeconds(31)))
        .expectComplete()
        .verify();
}

Here’s what’s happening:

  • We start with the value 0.
  • Every second, we increment the counter by one.
  • The process runs for 30 seconds.
  • The test waits until all increments are completed.

Step 6: Observing the Results

While the test is running, open your Redis CLI and check the key’s value:

GET user:visit:count

You’ll notice that the number keeps increasing every second, showing that the value is being updated atomically by Redis.

For example:

16
17
18
19
20
...

Once the test completes, the final count should be 30.


Step 7: Why Atomic Structures Are Useful

Using RAtomicLong and RAtomicDouble is very powerful for distributed systems because:

  • These operations are atomic — no race conditions occur even if multiple instances update the same key.
  • They are thread-safe and process-safe — perfect for counters, sequence IDs, rate-limiting, or statistics.
  • Redisson ensures Redis-level synchronization, so all updates are consistent across your cluster.

Step 8: Summary

Let’s summarize what we learned:

  1. RBucket is used for general key-value storage but doesn’t support numeric operations.
  2. For numeric operations, we should use RAtomicLong or RAtomicDouble.
  3. We can perform operations like:
    • incrementAndGet()
    • decrementAndGet()
    • addAndGet(value)
  4. These structures are atomic, distributed, and highly efficient.
  5. We used a reactive approach to observe continuous increments every second.

Example Output (in Redis CLI)

127.0.0.1:6379> GET user:visit:count
(integer) 30

This confirms that our Redisson client successfully performed atomic increments directly on the Redis server.