标签:Java String zooKeeper 优缺点 businessName znode public redisTemplate 分布式
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<Boolean> 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<Boolean> redisScript = RedisScript.of(script,Boolean.class);
List<String> 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<String> 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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。