scala分布式锁配置,工作中有使用分布式架构,当请求进入该方法时,不希望其他同一请求也进入,可以加上redisson分布式锁,
分布式锁配置:(文件名为:redisson.yaml)
singleServerConfig:
#连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
pingTimeout: 1000
#连接超时,单位:毫秒
connectTimeout: 10000
#命令等待超时,单位:毫秒
timeout: 3000
#命令失败重试次数
retryAttempts: 3
#命令重试发送时间间隔,单位:毫秒
retryInterval: 1500
#重新连接时间间隔,单位:毫秒
reconnectionTimeout: 3000
#执行失败最大次数
failedAttempts: 3
#单个连接最大订阅数量
subscriptionsPerConnection: 5
#客户端名称
clientName: null
#地址
address: "redis://123.56.5.77:32711"
#数据库编号
database: 0
#密码
password: null
#发布和订阅连接的最小空闲连接数
subscriptionConnectionMinimumIdleSize: 1
#发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
#最小空闲连接数
connectionMinimumIdleSize: 32
#连接池大小
connectionPoolSize: 64
#是否启用DNS监测
dnsMonitoring: false
#DNS监测时间间隔,单位:毫秒
dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode : "NIO"
添加依赖(一定要注意添加的redisson版本号,版本太低会报奇葩错误,一定先检查版本号)
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.1</version>
</dependency>
创建redisson对象
object ProductLocker {
var _redisson: Option[RedissonClient] = None
try {
val config = Config.fromYAML(new File("conf/redisson.yaml"))
_redisson = Some(Redisson.create(config))
} catch {
case ex: Throwable =>
Logger.debug(ex.toString)
_redisson = None
}
def lockVariation(productId: String): Option[RLock]= {
if (_redisson.nonEmpty) {
Logger.debug(s"Getting lock for ${productId}")
val lock = _redisson.get.getLock("VariationLock:" + productId)
lock.lock(30, TimeUnit.SECONDS)
Logger.debug(s"Locked for ${productId}")
Some(lock)
} else None
}
}
代码中使用分布式锁进行锁(只需要三行代码就可以加上分布式锁了)
简化版代码:
val rock = ProductLocker.lockVariation(userid)//创建rock(根据不同请求的用户加不同的锁)
rock map { case(x)=> x.tryLock(3, 10, TimeUnit.SECONDS) }//给方法加锁
//业务逻辑执行~~~~
rock.get.unlock()//执行完毕,关闭锁
scala完整代码使用示范
request =>
val rock = ProductLocker.lockVariation("patchDesign"+id)
try{
request.body.asJson.map{json =>
rock map {
case(x)=> x.tryLock(3, 10, TimeUnit.SECONDS)
}
val patchDto = json.as[PatchAssetDTO]
val dto = AuthPatchAssetDTO(id = id, session = session, assetDto = patchDto)
Logger.info("api patchDesign AuthPatchAssetDTO: " + dto)
comp.service.patchDesign(dto) map {
request =>
if(rock.nonEmpty) rock.get.unlock()
if(request.isError)
Ok(Json.toJson(request))
else
Ok(json)
}
}.getOrElse{
Future.successful(BadRequest("Incorrect Json data"))
}
} catch {
case e:InterruptedException=>
if(rock.nonEmpty) rock.get.unlock()
Logger.error("[AssetController]exception: " + e.getMessage)
Future.successful(BadRequest("Incorrect redisson err "))
}
}.getOrElse{
Future.successful(BadRequest("Incorrect Json data"))
}
}