scala+redis实现分布式锁的示例代码
1、redis的底层是单例模式,意思是同一个脚本同一时刻只能有一个线程来执行,利用redis的这个特性来实现分布式锁。
首先实现工具类
packageutils
importCacheManager
/**
*redis分布式锁
*/
objectRedisTool{
//加锁是否成功标志
valLOCK_SUCCESS:String="OK"
//即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;
valSET_IF_NOT_EXIST:String="NX"
//意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。
valSET_WITH_EXPIRE_TIME:String="PX"
valRELEASE_SUCCESS:String="1"
/**
*
*@paramlockKey锁
*@paramrequestId请求标识
*@paramexpireTime超期时间
*@paramisPersist临时缓存或者永久缓存
*/
deftryGetDistributedLock(lockKey:String,requestId:String,expireTime:Int,isPersist:Boolean=false){
CacheManager.redisClientPool.withClient(
client=>{
//valredisKeyPrefix=CacheManager.getRedisKeyPrefix(isPersist)
client.select(CacheManager.redisDBNum)
valresult=client.set(lockKey,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expireTime)
varflag=false
if(LOCK_SUCCESS==result){
flag=true
}
flag
}
)
}
/**
*释放分布式锁
*@paramlockKey锁
*@paramrequestId请求标识
*@paramexpireTime超期时间
*@paramisPersist临时缓存或者永久缓存
*@return
*/
defreleaseDistributedLock(lockKey:String,requestId:String,expireTime:Int=10,isPersist:Boolean=false)={
CacheManager.redisClientPool.withClient(
client=>{
valredisKeyPrefix=CacheManager.getRedisKeyPrefix(isPersist)
client.select(CacheManager.redisDBNum)
//lua脚本也是单例模式,同样也可以保证同一时刻只有一个线程执行脚本
vallua=
s"""
|localcurrent=redis.call('incrBy',KEYS[1],ARGV[1]);
|ifcurrent==tonumber(ARGV[1])then
|localt=redis.call('ttl',KEYS[1]);
|ift==-1then
|redis.call('expire',KEYS[1],ARGV[2])
|end;
|end;
|returncurrent;
""".stripMargin
valcode=client.scriptLoad(lua).get
valret=client.evalSHA(code,List(redisKeyPrefix+lockKey),List(requestId,expireTime))
valresult=ret.get.asInstanceOf[Object].toString
varflag=false
if(result==RELEASE_SUCCESS){
flag=true
}
flag
}
)
}
}
2、实现CacheManager类
packageutils
importcom.redis.RedisClientPool
/**
*
*/
objectCacheManager{
valredisClientPool="dev".equalsIgnoreCase(System.getenv("SCALA_ENV"))match{
//开发环境
casetrue=>newRedisClientPool("127.0.0.1",6379)
//其他环境
casefalse=>newRedisClientPool("10.180.x.y",6379,8,0,Some("root"))
}
valredisDBNum=10
defgetRedisKeyPrefix(isPersist:Boolean)={
if(isPersist){
//永久缓存前缀
"persist_"
}else{
//临时缓存前缀
"tmp_"
}
}
}
3、调用锁操作
defupdateTableInfo(param:String)={
varresMap=Map[String,Any]()
vallockKey="mdms.MdmsUtils.updateTableInfo"
//valrequestId=UUID.randomUUID().toString().replace("-","").toUpperCase()
valflag=RedisTool.releaseDistributedLock(lockKey,"1")
if(flag){
try{
//执行你的操作
resMap=Map("code"->200,"msg"->"成功")
}catch{
casee:Exception=>{
e.printStackTrace()
resMap=Map("code"->200101,"msg"->"执行失败")
}
}
}else{
resMap=Map("code"->200102,"msg"->"操作冲突,已经被其他人捷足先登啦。")
}
resMap
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。