分布式信号量 Semaphore

本文介绍如何使用Redisson实现基于Redis的分布式信号量Semaphore,通过模拟车库停车场景来演示其限流功能。支持阻塞和非阻塞两种方式,并提供异步、反射式及RxJava2等接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于Redis的Redisson的分布式信号量Semaphore;Java对象RSemaphore采用了与 juc 包下 Semaphore相似的接口和用法。同时还提供了异步(Async)、反射式(Reactive)、RxJava2标准的接口。

模拟车库停车, 3个车位

//停车
@GetMapping("/park")
@ResponseBody
public String  park() throws InterruptedException {
    // 在redis中存 pack = 3
    RSemaphore pack = redisson.getSemaphore("pack");
    pack.acquire(); //获取一个信号量,阻塞
    return "pack";
}

//离开
@GetMapping("/leave")
@ResponseBody
public String leave(){
    RSemaphore pack = redisson.getSemaphore("pack");
    pack.release();
    return "go";
}

测试:

访问:http://localhost:8080/park 3次,第四次时阻塞
访问:http://localhost:8080/leave ,上面通行

信号量也可以做分布式限流

@GetMapping("/park")
@ResponseBody
public String  park() throws InterruptedException {
    //在redis中存 pass = 10000,超过10000并发阻塞
    RSemaphore pack = redisson.getSemaphore("pass");
    boolean flag = pass.tryAcquire();//尝试获取一个信号量,不阻塞
    if(flag){
        //业务逻辑
    }else{
        return "error";
    }
}
### 分布式信号量的实现与使用 #### 什么是分布式信号量分布式信号量是一种用于控制多个线程或进程访问共享资源的技术,在分布式环境中尤其重要。它允许多个客户端竞争有限数量的许可,从而协调不同节点之间的操作[^1]。 #### 基于 Redis 的分布式信号量实现 一种常见的分布式信号量实现在 Redis 上完成,通常借助第三方库如 **Redisson** 来简化开发过程。以下是其实现的核心要点: - **RSemaphore 接口**:Redisson 提供了一个名为 `RSemaphore` 的类,该类实现了 Java 中的标准 `java.util.concurrent.Semaphore` 接口,并扩展了其功能以支持分布式环境下的信号量管理[^2]。 - **许可证分配机制**:每个信号量实例维护一组可用的许可证。当某个客户端请求获取许可证时,如果当前剩余许可证的数量大于零,则允许该请求并减少许可证计数器;否则,客户端会被阻塞直到有新的许可证可用[^3]。 - **非公平模式**:默认情况下,Redisson 的分布式信号量运行在非公平模式下,这意味着即使某些等待中的客户已经排队很久,新到来者仍可能立即获得许可而无需遵循严格的 FIFO 秩序[^3]。 #### 使用方法示例 下面是一个简单的例子展示了如何利用 Redisson 库创建和操作一个分布式信号量: ```java import org.redisson.Redisson; import org.redisson.api.RSemaphore; import org.redisson.api.RedissonClient; import org.redisson.config.Config; public class DistributedSemaphoreExample { public static void main(String[] args) throws InterruptedException { Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); // 创建 Redisson 客户端连接 RedissonClient redisson = Redisson.create(config); // 获取或者新建一个名字叫做 "myDistributedSemaphore" 的 RSemaphore 对象 RSemaphore semaphore = redisson.getSemaphore("myDistributedSemaphore"); try { // 初始化信号量, 设置最大并发数为3 semaphore.trySetPermits(3); System.out.println(Thread.currentThread().getName() + ": Trying to acquire permit..."); // 尝试获取一个许可 boolean couldAcquire = semaphore.tryAcquire(); if (couldAcquire){ System.out.println(Thread.currentThread().getName()+": Acquired a permit."); // 模拟业务逻辑处理耗时 Thread.sleep(2000); // 执行完毕后释放许可 semaphore.release(); System.out.println(Thread.currentThread().getName()+": Released the permit."); }else{ System.out.println(Thread.currentThread().getName()+": Could not get any permits at this moment."); } } finally { redisson.shutdown(); } } } ``` 此代码片段演示了怎样初始化一个具有三个初始许可的分布式信号量,并让不同的线程尝试去取得这些许可来进行他们的任务执行[^2]。 #### 注意事项 尽管 Redisson 提供了一种简便的方式来构建跨服务器通信的应用程序组件,但在实际部署过程中可能会遇到一些潜在的问题需要注意: - 网络延迟可能导致性能下降; - 如果主 Redis 节点发生故障,则整个系统都不可用除非配置高可用架构; - 需要合理设置超时时间和重试策略以防死锁情况的发生[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值