vlambda博客
学习文章列表

秒杀redis分布式锁

今天在视频中看到了一种redis锁的方法
下面看我的demo代码

<?php
$redis = new \Redis();

if ($redis->connect('127.0.0.1','6379') == false) {
die($redis->getLastError());
}


/**
* [lock 加锁]
* @Author [email protected]
* @DateTime 2017-11-28T14:48:48+0800
* @param [type] $redis [description]
* @param [type] $key 产品ID
* @param [type] $value 当前时间戳+超时时间戳
* @return [type] [description]
*/
function lock($redis,$key,$value){

//如果可以成功设置就返回true
$ok =$redis->setNx($key,$value);

if($ok){
return true;
}

$currentValue= $redis->get($key);
//锁过期
if(!empty($currentValue) && $currentValue<time()){
//获得上一个锁
$oldValue=$redis->getSet($key,$value);
if(!empty($oldValue) && $oldValue==$currentValue){
return true;
}
}

return false;
}
/**
* [unlock 结锁]
* @Author [email protected]
* @DateTime 2017-11-28T14:49:27+0800
* @param [type] $redis [description]
* @param [type] $key [description]
* @param [type] $value [description]
* @return [type] [description]
*/
function unlock($redis,$key,$value){
try {
$currentValue=$redis->get($key);
if(!empty($currentValue) && $currentValue==$value){
$redis->del($key);
}
}catch(Exception $e) {

}
}


$product_id=10;
$time=time()+10*1000;
//加锁
$lock=lock($redis,$product_id,$time);
if(!$lock){
exit;
}

$mywatchkey=$redis->get("mywatchkey");
if($mywatchkey<10){
$redis->set("mywatchkey",$mywatchkey+1);
}
//解锁
unlock($redis,$product_id,$time);

用ab测试过没有问题,上面的代码是用java代码修改过来的
java代码的锁文件

package com.imooc.sell.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Slf4j
@Component
public class RedisLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public boolean lock(String key,String value){
if(stringRedisTemplate.opsForValue().setIfAbsent(key,value)){
return true;
}
String currentValue=stringRedisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue)<System.currentTimeMillis()){
String oldValue=stringRedisTemplate.opsForValue().getAndSet(key,value);
if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
return true;
}
}