您的位置:首页 > 数据库 > Redis

基于redis的分布式锁的实现

2017-02-07 10:51 519 查看
之前一直对分布式锁有所思考。一直觉得现在高性能的redis是个不错的选择;

前文:关于分布式锁的思考

今天也尝试着写了一个基于redis的分布式锁工具

LockUtil.java

package yyf.Jedis.toolsByRedis;

import java.util.concurrent.atomic.AtomicInteger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
* 基于redis的分布式锁工具
*
* @author yuyufeng
*
*/
public class LockUtil {

// 获取redis
static JedisPool jedisPool;
static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(5);
config.setMaxWaitMillis(1000);
config.setTestOnBorrow(false);

// 构造池
jedisPool = new JedisPool(config, "127.0.0.1", 6379, 1000, "12345");
}

// redis键值前缀标识
private final static String PREFIX = "LOCK-FLAG-";
// 默认获取锁的等待时间
private final static Integer WAITTIME = 200;

/**
* 获取锁
*
* @param uid:锁的唯一标识
* @param expire:锁自动释放时间
* @return true:获得锁;false:锁已被占用
*/
public static Boolean getLock(String uid, Integer expire) {
if (expire < 0) {
return false;
}
Long beginTime = System.currentTimeMillis();
do {
Jedis jedis = jedisPool.getResource();

//防止程序出错设置键值不失效
if(jedis.ttl(PREFIX + uid) == -1){
jedis.expire(PREFIX + uid, expire);
}

Long res = jedis.incr(PREFIX + uid);

if (res == 1) {
jedis.expire(PREFIX + uid, expire);

if (jedis != null) {
try {
jedis.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}

return true;
}

if (jedis != null) {
try {
jedis.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(".");
} while ((System.currentTimeMillis() - beginTime) < WAITTIME);

return false;
}

/**
* 获取锁
*
* @param uid:锁的唯一标识
* @param expire:锁自动释放时间
* @param timeout:超时等待时间
* @return true:获得锁;false:锁已被占用
*/
public static Boolean getLock(String uid, Integer expire, Integer timeout) {
if (expire < 0) {
return false;
}
Long beginTime = System.currentTimeMillis();
do {
Jedis jedis = jedisPool.getResource();

//防止程序出错设置键值不失效
if(jedis.ttl(PREFIX + uid) == -1){
jedis.expire(PREFIX + uid, expire);
}

Long res = jedis.incr(PREFIX + uid);

if (res == 1) {
jedis.expire(PREFIX + uid, expire);

if (jedis != null) {
try {
jedis.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}

return true;
}

if (jedis != null) {
try {
jedis.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(".");
} while ((System.currentTimeMillis() - beginTime) < timeout);

return false;
}

/**
* 手动释放锁
*
* @param uid:锁的唯一标识
*/
public static void returnLock(String uid) {
Jedis jedis = jedisPool.getResource();
jedis.del(PREFIX + uid);
if (jedis != null) {
try {
jedis.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
System.out.println("手动释放锁:" + uid);
}

/**
* 测试
*
* @param args
*/
public static void main(String[] args) {

AtomicInteger ai = new AtomicInteger(1);
AtomicInteger count = new AtomicInteger(0);
for (int i = 0; i < 30; i++) {
new Thread() {
@Override
public void run() {
String uid = "a" + ai.incrementAndGet() % 10; // 获取锁,并设置10秒失效
Boolean lock = LockUtil.getLock(uid, 10);
System.out.println(uid + "取锁结果:" + lock);
if (lock) {
// dosomething..
count.incrementAndGet();
}
System.out.println("当前获取锁的数量:"+count);
}
}.start();
}

// 手动解锁测试,超时测试
//Boolean lock = LockUtil.getLock("testReturnKey", 1);
//System.out.println("testReturnKey" + "取锁结果:" + lock);
// LockUtil.returnLock("testReturnKey");

}

}


给出其中连续的两次运行测试结果吧:

第一次运行(预期获得10个锁):

a7取锁结果:true
当前获取锁的数量:1
a2取锁结果:true
当前获取锁的数量:2
a1取锁结果:true
当前获取锁的数量:3
a3取锁结果:true
当前获取锁的数量:4
a9取锁结果:true
当前获取锁的数量:5
a8取锁结果:true
当前获取锁的数量:6
a0取锁结果:true
当前获取锁的数量:7
a5取锁结果:true
当前获取锁的数量:8
a6取锁结果:true
当前获取锁的数量:9
a4取锁结果:true
当前获取锁的数量:10
......................a4取锁结果:false
a7取锁结果:false
当前获取锁的数量:10
当前获取锁的数量:10
..a5取锁结果:false
a6取锁结果:false
当前获取锁的数量:10
...当前获取锁的数量:10
a3取锁结果:false
a6取锁结果:false
a9取锁结果:false
当前获取锁的数量:10
当前获取锁的数量:10
当前获取锁的数量:10
.a5取锁结果:false
当前获取锁的数量:10
.a8取锁结果:false
当前获取锁的数量:10
..a4取锁结果:false
a0取锁结果:false
当前获取锁的数量:10
当前获取锁的数量:10
..a1取锁结果:false
a3取锁结果:false
当前获取锁的数量:10
当前获取锁的数量:10
.a0取锁结果:false
当前获取锁的数量:10
.a9取锁结果:false
当前获取锁的数量:10
.a7取锁结果:false
当前获取锁的数量:10
.a2取锁结果:false
当前获取锁的数量:10
.a8取锁结果:false
当前获取锁的数量:10
..a1取锁结果:false
a2取锁结果:false
当前获取锁的数量:10
当前获取锁的数量:10

接着马上运行第二次(预期就是10秒内全部不能获得锁):

...............................a6取锁结果:false
当前获取锁的数量:0
.a0取锁结果:false
当前获取锁的数量:0
.a5取锁结果:false
当前获取锁的数量:0
.a9取锁结果:false
.a3取锁结果:false
当前获取锁的数量:0
.a7取锁结果:false
当前获取锁的数量:0
.a1取锁结果:false
当前获取锁的数量:0
当前获取锁的数量:0
.a9取锁结果:false
当前获取锁的数量:0
.a8取锁结果:false
.a7取锁结果:false
当前获取锁的数量:0
.a3取锁结果:false
当前获取锁的数量:0
...当前获取锁的数量:0
.a8取锁结果:false
当前获取锁的数量:0
a4取锁结果:false
当前获取锁的数量:0
a0取锁结果:false
当前获取锁的数量:0
a2取锁结果:false
当前获取锁的数量:0
.a4取锁结果:false
当前获取锁的数量:0
...a1取锁结果:false
a9取锁结果:false
当前获取锁的数量:0
a5取锁结果:false
当前获取锁的数量:0
当前获取锁的数量:0
....a2取锁结果:false
.a0取锁结果:false
当前获取锁的数量:0
a1取锁结果:false
a7取锁结果:false
.a4取锁结果:false
当前获取锁的数量:0
a2取锁结果:false
当前获取锁的数量:0
..a8取锁结果:false
.当前获取锁的数量:0
当前获取锁的数量:0
a6取锁结果:false
当前获取锁的数量:0
.a5取锁结果:false
a3取锁结果:false
当前获取锁的数量:0
当前获取锁的数量:0
当前获取锁的数量:0
当前获取锁的数量:0
.a6取锁结果:false
当前获取锁的数量:0


效果还是很理想的。有待实践吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: