可过期信号量并发控制

可过期信号量并发控制

需求背景

供应商提供的接口,单个账号存在并发限制,超出并发数就会报错,并且支持并发数较低,经常会因为高频调用而导致报错。

而供应商暂时不支持提高单个账号的并发数,给出的解决方案是提供多个账号。账号为次数充值账号,需要尽量做到次数均衡使用。

问题分析

我们需要保证接口不会因为并发数上限而报错的前提下,充分的使用多个账号的并发数,同时保证并发控制的效率:

  1. 请求排队:需要根据总并发数,控制超出并发时,所有请求进入同一队列等待,先进先出

  2. 集群支持:所有服务集群共享多个账号,需要支持集群的并发控制

  3. 账号分配:请求进入处理后,取用有空闲并发的账号进行处理

  4. 轮询处理:通过轮询的机制,均衡分配各账号的请求数

为保证并发的控制支持集群,我们需要使用到中间件进行协助处理,Redis、Mq或者数据库。

数据库效率太低,直接不考虑

对比Redis和Mq,Redis本身支持轻量级的mq,我们只需要的支持到排队、类似令牌桶的处理量控制,Redis均能满足,且有工具包能使用,满足我们的需求。

解决方案

我们可以通过redisson框架提供的 可过期信号量 RPermitExpirableSemaphore 实现我们的功能

RPermitExpirableSemaphore 提供的功能:

// 创建信号量池, 设置总信号量数,建议在应用功能启动时初始化
RPermitExpirableSemaphore totalSemaphore = redissonClient.getPermitExpirableSemaphore(TOTAL_SEMAPHORE_KEY);
totalSemaphore.trySetPermits(30);

// acquire方法获取信号量,信号量已满则进入队列等待。信号量持有时间超出 TIMEOUT_SECOND 会自动释放
// 用于控制总并发,排队
RPermitExpirableSemaphore totalSemaphore = redissonClient.getPermitExpirableSemaphore(TOTAL_SEMAPHORE_KEY);
String totalPermitId = totalSemaphore.acquire(TIMEOUT_SECOND, TimeUnit.SECONDS);

// tryAcquire尝试获取信号量,信号量已满则返回null,不等待。信号量持有时间超出 TIMEOUT_SECOND 会自动释放
// 用于分配账号
RPermitExpirableSemaphore accountSemaphore = redissonClient.getPermitExpirableSemaphore(ACCOUNT_SEMAPHORE_KEY_SUFFIX + account.getAppKey());
String accountPermitId = accountSemaphore.tryAcquire(0, TIMEOUT_SECOND, TimeUnit.SECONDS);

// 处理完毕后主动释信号量
RPermitExpirableSemaphore totalSemaphore = redissonClient.getPermitExpirableSemaphore(TOTAL_SEMAPHORE_KEY);
totalSemaphore.release(totalPermitId);

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值