欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-25 20:23:05
1、redis的底层是单例模式,意思是同一个脚本同一时刻只能有一个线程来执行,利用redis的这个特性来实现分布式锁。 首先实现工具类 package util...

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
 }

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