Red-Utils

Distributed Lock Implementation With Redis

License

License

GroupId

GroupId

com.github.siahsang
ArtifactId

ArtifactId

red-utils
Last Version

Last Version

1.0.4
Release Date

Release Date

Type

Type

jar
Description

Description

Red-Utils
Distributed Lock Implementation With Redis
Project URL

Project URL

https://github.com/siahsang/red-utils
Source Code Management

Source Code Management

https://github.com/siahsang/red-utils

Download red-utils

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.siahsang/red-utils/ -->
<dependency>
    <groupId>com.github.siahsang</groupId>
    <artifactId>red-utils</artifactId>
    <version>1.0.4</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.siahsang/red-utils/
implementation 'com.github.siahsang:red-utils:1.0.4'
// https://jarcasting.com/artifacts/com.github.siahsang/red-utils/
implementation ("com.github.siahsang:red-utils:1.0.4")
'com.github.siahsang:red-utils:jar:1.0.4'
<dependency org="com.github.siahsang" name="red-utils" rev="1.0.4">
  <artifact name="red-utils" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.siahsang', module='red-utils', version='1.0.4')
)
libraryDependencies += "com.github.siahsang" % "red-utils" % "1.0.4"
[com.github.siahsang/red-utils "1.0.4"]

Dependencies

compile (2)

Group / Artifact Type Version
redis.clients : jedis jar 3.3.0
org.slf4j : slf4j-simple jar 1.7.30

test (5)

Group / Artifact Type Version
org.junit.jupiter : junit-jupiter jar 5.7.0
org.junit.jupiter : junit-jupiter-params jar 5.7.0
org.awaitility : awaitility jar 4.0.3
org.testcontainers : testcontainers jar 1.15.2
org.testcontainers : junit-jupiter jar 1.15.1

Project Modules

There are no modules declared in this project.

RedUtils

Distributed Lock Implementation With Redis

license Build Status

Note

For reading the idea and the algorithm behind this, please visit https://dzone.com/articles/distributed-lock-implementation-with-redis

Introduction

RedUtils is a distributed lock and using Redis for storing and expiring locks. It has the following features:

  • Leased-Based Lock: If any clients crash or restarted abnormally, eventually lock will be free.
  • Safe: Provided that fsync=always on every Redis instance we have safety even if Redis become unavailable after getting lock.
  • Auto-Refreshing Lock: A lock that is acquired by the client can be held as long as the client is alive, and the connection is OK.

Getting Started

Requirements

Install Redis or use the following command if you have Docker installed

docker run --name some-redis  -e ALLOW_EMPTY_PASSWORD=yes -p 6379:6379 --rm -it redis

Add the following dependency (Java 8 is required)

<dependency>
    <groupId>com.github.siahsang</groupId>
    <artifactId>red-utils</artifactId>
    <version>1.0.4</version>
</dependency>

How to use it?

Getting the lock with the default configuration. Wait for getting the lock if it is acquired by another thread.

RedUtilsLock redUtilsLock = new RedUtilsLockImpl();
redUtilsLock.acquire("lock1", () -> {
    // some operation
});

Try to acquire the lock and return true after executing the operation, otherwise, return false immediately.

RedUtilsLock redUtilsLock = new RedUtilsLockImpl();
boolean getLockSuccessfully = redUtilsLock.tryAcquire("lock1", () -> {
    // some operation
});

You can also provide configuration when initializing RedUtilsLock

RedUtilsConfig redUtilsConfig = new RedUtilsConfig.RedUtilsConfigBuilder()
            .hostAddress("127.0.0.1")
            .port("6379")
            .replicaCount(3)
            .leaseTimeMillis(40_000)
            .build();

RedUtilsLock redUtilsLock = new RedUtilsLockImpl(redUtilsConfig);

To see more examples please see the tests

Running the tests

For running the tests, you should install Docker(test cases use testcontainer for running Redis). After that you can run all tests with:

mvn clean test

Caveats

There are some caveats that you should be aware of:

  1. I assume clocks are synchronized between different nodes.
  2. I assume there aren't any long thread pause or process pause after getting lock but before using it.
  3. To achieve strong consistency you should enable the option fsync=always on every Redis instance.
  4. In current implementation, locks is not fair; for example, a client may wait a long time to get the lock and at the same time another client get the lock immediately.

Dependencies

  • Jedis
  • Slf4j

Versions

Version
1.0.4