> For the complete documentation index, see [llms.txt](https://xu-min-chang.gitbook.io/caster-develop-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xu-min-chang.gitbook.io/caster-develop-note/java/redis/redisson-fen-bu-shi-suo-ji-zhi.md).

# Redisson 分布式鎖機制

Redisson 是一個用於 Java 的分布式和分散式應用程序的高級框架，提供了多種分布式數據結構和服務。其中，分布式鎖是 Redisson 提供的重要功能之一。

分布式鎖的設計旨在在多個應用程序實例或多個線程之間實現協調，以確保只有一個實例（或線程）可以訪問關鍵區域，防止資源的併發競爭，確保數據的一致性和可靠性。

Redisson 分布式鎖的設計思想如下：

1. **鎖的獲取與釋放：** 使用 `RLock` 接口進行鎖的操作，可以通過 `tryLock` 方法嘗試獲取鎖，並通過 `unlock` 方法釋放鎖。
2. **鎖的可重入性：** Redisson 支持可重入鎖，即同一個線程可以多次獲取同一把鎖，且每次獲取都需要對應的解鎖操作。
3. **過期時間：** 可以為每個鎖設置過期時間，避免因為應用程序異常導致鎖一直佔用。
4. **阻塞與非阻塞：** `tryLock` 方法可以指定等待的時間，如果無法立即獲取到鎖，可以阻塞或者等待一段時間。
5. **監視狀態：** Redisson 提供了監視機制，可以監視鎖的狀態，如果鎖被釋放，通知等待的實例進行競爭。
6. **分佈式：** Redisson 鎖是基於 Redis 實現的，因此可以實現分佈式環境下的鎖。

使用 Redisson 分布式鎖時需要注意以下幾點：

* 鎖的名稱應該是全局唯一的，以確保不同的實例可以協調。
* 鎖的獲取和釋放應該處於同一個代碼區塊內，確保鎖在正確的時機被釋放。
* 選擇適當的鎖的超時時間和等待策略，以避免死鎖和無限等待。

#### 測試範例

```java

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.LongCodec;
import org.redisson.config.Config;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class RedissonLockTest {

    public static final String REDISSON_LOCK = "redisson";

    public static void main(String[] args) throws InterruptedException {
        RedissonClient redissonClient = redissonClient();
        try {
            RLock rLock = redissonClient.getLock(REDISSON_LOCK);

            // 嘗試鎖定
            rLock.tryLock();

            printLog("using lock.");

            // 創建一個新的線程
            List.of(3,5).forEach(o -> newAThread(redissonClient, o));
//            newAThread(redissonClient);

            int second = 5;
            printLog(String.format("sleep %s(s).", second));
            TimeUnit.SECONDS.sleep(second);

            // 如果當前線程鎖住並且持有該鎖
            if (rLock.isLocked() && rLock.isHeldByCurrentThread())
                rLock.unlock();

            printLog("release lock success.");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            TimeUnit.SECONDS.sleep(20);

            // 關閉 Redisson 客戶端
            redissonClient.shutdown();
        }

        TimeUnit.SECONDS.sleep(2);
        System.exit(0);
    }

    public static void newAThread(RedissonClient redissonClient, int i) {
        new Thread(() -> {
            try {
                // 創建一個 Redisson 分布式鎖
                RLock anotherLock = redissonClient.getLock(REDISSON_LOCK);

                // 創建一個 Redisson 訂閱主題
                RTopic topic = redissonClient.getTopic("redisson_lock__channel:{redisson}", LongCodec.INSTANCE);
//                RPatternTopic patternTopic = redissonClient.getPatternTopic("*", LongCodec.INSTANCE); // 亦可使用Regex 方式

                // 添加訂閱者到訂閱主題
                int topicId = topic.addListener(Long.class, (channel, msg) -> printLog(String.format("RTopic => channel:%s, message:%s", channel, msg)));

                // 嘗試鎖住
//                boolean lockSuccess = anotherLock.tryLock(2, TimeUnit.SECONDS);
                boolean lockSuccess = anotherLock.tryLock(5, 1, TimeUnit.SECONDS); // 等待時間內收到釋放鎖消息，則重新去競爭鎖
//                boolean lockSuccess = anotherLock.tryLock(2, 1, TimeUnit.SECONDS); // 等待時間內未獲得鎖直接回傳結果。
//                boolean lockSuccess = anotherLock.tryLock(); // 未設置等待時間，則直接判斷當前是否取到鎖
                if (lockSuccess) {
                    printLog("try lock success.");

                    TimeUnit.SECONDS.sleep(i);

                    // 如果當前線程鎖住並且持有該鎖
                    if (anotherLock.isLocked() && anotherLock.isHeldByCurrentThread()) {
                        anotherLock.unlock();
                        printLog("release lock success.");
                    }
                } else {
                    printLog("try lock failed.");
                }

                // 移除訂閱者
                topic.removeListener(topicId);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "Thread_" + i).start();
    }


    static void printLog(String message) {
        System.out.println(String.format("%s - [%s] -> %s", LocalDateTime.now(), Thread.currentThread().getName(), message));
    }

    private static RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://172.20.160.120:6379");
        config.setLockWatchdogTimeout(TimeUnit.SECONDS.toMillis(10));
        return Redisson.create(config);
    }
}
```

總而言之，Redisson 提供了方便易用的 API 來實現分布式鎖，這有助於處理多實例或多線程的併發問題，確保數據操作的一致性和可靠性。
