当前位置: 移动技术网 > IT编程>开发语言>Java > scala+redis实现分布式锁的示例代码

scala+redis实现分布式锁的示例代码

2019年07月19日  | 移动技术网IT编程  | 我要评论

1、redis的底层是单例模式,意思是同一个脚本同一时刻只能有一个线程来执行,利用redis的这个特性来实现分布式锁。

首先实现工具类

package utils
 
import cachemanager
 
/**
 * redis分布式锁
 */
object redistool {
 
 //加锁是否成功标志
 val lock_success:string = "ok"
 
 //即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;
 val set_if_not_exist:string = "nx"
 
 //意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。
 val set_with_expire_time:string = "px"
 
 val release_success:string = "1"
 
 /**
  *
  * @param lockkey   锁
  * @param requestid  请求标识
  * @param expiretime  超期时间
  * @param ispersist  临时缓存或者永久缓存
  */
 def trygetdistributedlock(lockkey:string, requestid:string, expiretime:int,ispersist:boolean=false){
  cachemanager.redisclientpool.withclient(
   client => {
    //val rediskeyprefix = cachemanager.getrediskeyprefix(ispersist)
    client.select(cachemanager.redisdbnum)
    val result = client.set(lockkey, requestid, set_if_not_exist, set_with_expire_time, expiretime)
    var flag = false
    if(lock_success == result){
     flag = true
    }
    flag
   }
  )
 }
 
 
 /**
  *释放分布式锁
  * @param lockkey   锁
  * @param requestid  请求标识
  * @param expiretime  超期时间
  * @param ispersist  临时缓存或者永久缓存
  * @return
  */
 def releasedistributedlock(lockkey:string, requestid:string,expiretime: int = 10,ispersist:boolean=false) ={
  cachemanager.redisclientpool.withclient(
   client => {
    val rediskeyprefix = cachemanager.getrediskeyprefix(ispersist)
    client.select(cachemanager.redisdbnum)
    //lua脚本也是单例模式,同样也可以保证同一时刻只有一个线程执行脚本
    val lua =
     s"""
       |local current = redis.call('incrby',keys[1],argv[1]);
       |if current == tonumber(argv[1]) then
       |  local t = redis.call('ttl',keys[1]);
       |  if t == -1 then
       |    redis.call('expire',keys[1],argv[2])
       |  end;
       |end;
       |return current;
      """.stripmargin
    val code = client.scriptload(lua).get
    val ret = client.evalsha(code, list(rediskeyprefix + lockkey),list(requestid,expiretime))
    val result = ret.get.asinstanceof[object].tostring
    var flag = false
    if(result == release_success){
     flag = true
    }
    flag
   }
  )
 }
 
}

2、实现cachemanager类

package utils
 
import com.redis.redisclientpool
/**
 * 
 */
object cachemanager {
 
 val redisclientpool = "dev".equalsignorecase(system.getenv("scala_env")) match {
  //开发环境
  case true => new redisclientpool("127.0.0.1", 6379)
  //其他环境
  case false => new redisclientpool("10.180.x.y", 6379, 8, 0, some("root"))
 }
 
 val redisdbnum = 10
 
 def getrediskeyprefix(ispersist:boolean) ={
  if(ispersist){
   //永久缓存前缀
   "persist_"
  }else{
   //临时缓存前缀
   "tmp_"
  }
 }
 
}

3、调用锁操作

def updatetableinfo(param:string) = {
  var resmap = map[string,any]()
  val lockkey = "mdms.mdmsutils.updatetableinfo"
  //val requestid = uuid.randomuuid().tostring().replace("-", "").touppercase()
  val flag = redistool.releasedistributedlock(lockkey, "1")
  if(flag){
   try{
    
    //执行你的操作
    resmap = map("code" -> 200 ,"msg" -> "成功")
   }catch {
    case e:exception => {
     
     e.printstacktrace()
     resmap = map("code" -> 200101 ,"msg" -> "执行失败")
    }
   }
   
  }else{
   resmap = map("code" -> 200102 ,"msg" -> "操作冲突,已经被其他人捷足先登啦。")
  }
  resmap
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网