java中分布式锁_Java中分布式锁的不同实现,以及优缺点对比

Java中分布式锁的应用

本文只做引导,具体实现可能需要另行搜索

SQL | Redis | Zookeeper | Curator | Redisson 对比

数据库层级

建立两个数据库,一个是业务库,一个是锁库

正常些Service代码

在锁库创建表, 字段是锁的名字

利用怕他锁 select * from 表 where 锁的字段= 锁的名字 for update

正常写代码

Redis

public class RedisLock implements AutoCloseable {

private RedisTemplate redisTemplate;

private String key;

private String value;

//单位:秒

private int expireTime;

public RedisLock(RedisTemplate redisTemplate,String key,int expireTime){

this.redisTemplate = redisTemplate;

this.key = key;

this.expireTime=expireTime;

this.value = UUID.randomUUID().toString();

}

/**

* 获取分布式锁

* @return

*/

public boolean getLock(){

RedisCallback redisCallback = connection -> {

//设置NX

RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();

//设置过期时间

Expiration expiration = Expiration.seconds(expireTime);

//序列化key

byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);

//序列化value

byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);

//执行setnx操作

Boolean result = connection.set(redisKey, redisValue, expiration, setOption);

return result;

};

//获取分布式锁

Boolean lock = (Boolean)redisTemplate.execute(redisCallback);

return lock;

}

public boolean unLock() {

String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +

" return redis.call(\"del\",KEYS[1])\n" +

"else\n" +

" return 0\n" +

"end";

RedisScript redisScript = RedisScript.of(script,Boolean.class);

List keys = Arrays.asList(key);

Boolean result = (Boolean)redisTemplate.execute(redisScript, keys, value);

log.info("释放锁的结果:"+result);

return result;

}

@Override

public void close() throws Exception {

unLock();

}

}

----------------

## 使用

try (RedisLock redisLock = new RedisLock(redisTemplate,"redisKey",30)){

if (redisLock.getLock()) {

log.info("我进入了锁!!");

Thread.sleep(15000);

}

} catch (InterruptedException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

ZooKeeper

public class ZkLock implements Watcher,AutoCloseable {

private ZooKeeper zooKeeper;

private String businessName;

private String znode;

public ZkLock(String connectString,String businessName) throws IOException {

this.zooKeeper = new ZooKeeper(connectString,30000,this);

this.businessName = businessName;

}

public boolean getLock() throws KeeperException, InterruptedException {

Stat existsNode = zooKeeper.exists("/" + businessName, false);

if (existsNode == null){

zooKeeper.create("/" + businessName,businessName.getBytes(),

ZooDefs.Ids.OPEN_ACL_UNSAFE,

CreateMode.PERSISTENT);

}

znode = zooKeeper.create("/" + businessName + "/" + businessName + "_", businessName.getBytes(),

ZooDefs.Ids.OPEN_ACL_UNSAFE,

CreateMode.EPHEMERAL_SEQUENTIAL);

znode = znode.substring(znode.lastIndexOf("/")+1);

List childrenNodes = zooKeeper.getChildren("/" + businessName, false);

Collections.sort(childrenNodes);

String firstNode = childrenNodes.get(0);

if (!firstNode.equals(znode)){

String lastNode = firstNode;

for (String node:childrenNodes){

if (!znode.equals(node)){

lastNode = node;

}else {

zooKeeper.exists("/"+businessName+"/"+lastNode,true);

break;

}

}

synchronized (this){

wait();

}

}

return true;

}

@Override

public void process(WatchedEvent watchedEvent) {

if (watchedEvent.getType() == Event.EventType.NodeDeleted){

synchronized (this){

notify();

}

}

}

@Override

public void close() throws Exception {

zooKeeper.delete("/"+businessName+"/"+znode,-1);

zooKeeper.close();

}

}

----------------

## 使用

try (ZkLock zkLock = new ZkLock("localhost:2181","order")){

if (zkLock.getLock()) {

log.info("我进入了锁!!");

Thread.sleep(15000);

}

} catch (InterruptedException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

Curator

Redisson

优缺点对比

实现优点缺点SQL实现简单,容易理解对数据库压力大

Redis容易理解不支持阻塞

Zookeeper支持阻塞需要了解ZK,程序复杂

Curator提供现成锁的方法依赖Zookeeper,强一致

Redisson提供线程锁的方法

标签:Java,String,zooKeeper,优缺点,businessName,znode,public,redisTemplate,分布式

来源: https://blog.csdn.net/cocoa_geforce/article/details/111305359

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值