Mastering Redis Optimistic Lock in Spring Boot: A Hands‑On Guide

This tutorial explains how Redis optimistic locking works, demonstrates the WATCH, MULTI, EXEC, and DISCARD commands with live examples, and shows how to integrate the mechanism into a Spring Boot application using retry logic to handle concurrent updates safely.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Redis Optimistic Lock in Spring Boot: A Hands‑On Guide

1. Introduction

Redis optimistic lock is a concurrency control method that assumes concurrent transactions do not interfere and can operate on their own data without acquiring locks. It works by watching keys and aborting the transaction if a watched key changes before execution.

2. Redis client demonstration

WATCH

127.0.0.1:6379> help watch
WATCH key [key ...]
summary: Observe given keys to determine execution of MULTI/EXEC block
since: 2.2.0
group: transactions

MULTI

127.0.0.1:6379> help multi
MULTI -
summary: Mark the start of a transaction block
since: 1.2.0
group: transactions

After the MULTI command, subsequent commands are queued and will only be executed when EXEC is called or discarded with DISCARD.

EXEC

127.0.0.1:6379> help exec
summary: Execute all commands issued after MULTI
since: 1.2.0
group: transactions

DISCARD

127.0.0.1:6379> help discard
summary: Discard all commands issued after MULTI
since: 2.0.0
group: transactions

MULTI / EXEC / DISCARD demo

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET a 1
QUEUED
127.0.0.1:6379(TX)> INCR a
QUEUED
127.0.0.1:6379(TX)> SET b 1
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (integer) 2
3) OK

All commands are queued after MULTI and executed sequentially by EXEC.

WATCH demo

Open two terminal windows. In the first window execute WATCH, MULTI and queue commands without calling EXEC. In the second window increment the watched key, causing the transaction in the first window to fail when EXEC is finally called.

# Window 1
127.0.0.1:6379> SET version 1
OK
127.0.0.1:6379> WATCH version
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET a 1
QUEUED
127.0.0.1:6379(TX)> SET b 1
QUEUED
# (do not EXEC yet)

# Window 2
127.0.0.1:6379> INCR version
(integer) 2

# Back to Window 1
127.0.0.1:6379(TX)> EXEC
(nil)
127.0.0.1:6379> KEYS *
1) "version"

The EXEC returns nil because the watched key was modified, demonstrating the optimistic lock behavior.

3. Application in Spring Boot

Dependency

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Redis configuration (application.yml)

spring:
  redis:
    host: localhost
    port: 6379
    password:
    lettuce:
      pool:
        maxActive: 8
        maxIdle: 100
        minIdle: 10
        maxWait: -1

Code implementation

@Resource
private StringRedisTemplate stringRedisTemplate;

// Retry when IllegalStateException occurs, up to 3 attempts
@Retryable(maxAttempts = 3, value = {IllegalStateException.class})
public List<Object> watch() {
  List<Object> ret = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
    @Override
    public List<Object> execute(RedisOperations opt) throws DataAccessException {
      // watch the key
      opt.watch("v");
      // start transaction block
      opt.multi();
      opt.opsForValue().increment("v");
      // execute queued commands
      return opt.exec();
    }
  });
  // If the transaction was discarded, ret will be null/empty, trigger retry
  if (ret == null || ret.isEmpty()) {
    System.err.printf("Retry...%n");
    throw new IllegalStateException("Data was modified");
  }
  return ret;
}

Summary: By using Redis's WATCH mechanism together with Spring Boot's transaction support and a retry framework, you can implement an optimistic lock that safely handles concurrent updates. The lock aborts the transaction if the watched key changes, requiring a retry that may affect performance, so it should be used after careful consideration of the business scenario.

Redis optimistic lock diagram
Redis optimistic lock diagram
Spring Boot integration
Spring Boot integration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

transactionspring-bootoptimistic-lock
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.