前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis和zk实现分布式锁有什么区别_redis分布式锁和zk分布式锁区别

redis和zk实现分布式锁有什么区别_redis分布式锁和zk分布式锁区别

作者头像
全栈程序员站长
发布2022-10-04 19:17:19
3630
发布2022-10-04 19:17:19
举报

大家好,又见面了,我是你们的朋友全栈君。

前言

本文介绍下分布式锁的一个使用场景 分享本文的缘由是因为今天在写代码时需要处理一个原子性问题,场景是:业务功能需要先查询数据,再根据数据判断是否要更新数据,在这个查询+更新的过程必然会存在高并发下的原子性问题

那么如何解决这个问题呢,那么就要说到我们的主角:分布式锁了

分布式锁介绍

分布式锁:即在多集群多节点环境下确保只有一个线程可以拿到锁,防止并发出现的问题,类似于synchronized,只不过synchronized不能处理多节点的问题

解决上述问题的一种解决方式就是使用分布式锁,虽然性能会比较低,但是笔者的场景是一个统计功能,并且是异步的,所以并不影响性能 核心代码如下:

场景介绍

代码语言:javascript
复制
try { 

// 这里可以根据业务场景做分段锁,可以适当提升性能
String lock = "lock_key";
long keyValue = System.currentTimeMillis();
// 获取锁,超时时间60秒每隔0.5秒尝试获取一次,60秒后没获取到则放弃
boolean getLock = redisUtils.getLockByInterval(lock,keyValue,60,0.5,0);
if(getLock) { 

xxx
}
} catch (Exception e) { 

log.error("异常:", e);
} finally { 

if(getLock) { 

redisUtils.unLock(lock,keyValue);
}
}

RedisUtils类getLockByInterval

代码语言:javascript
复制
  /** * 获取锁,如果没获取到那么每隔interval秒重试一次,重试直到timeout秒 * @param key * @param value * @param timeout 超时时间(单位秒) * @param interval 超时时间(单位秒) * @param currentTime 当前时间,调用时传0,只用于递归时间 * @return */
public boolean getLockByInterval(String key,Object value,int timeout,double interval,double currentTime) { 

if(currentTime > timeout) { 

return false;
}
// 相当于redis的setnx命令
boolean getLock = redisTemplate.opsForValue().setIfAbsent(key,value,timeout, TimeUnit.SECONDS);
if(!getLock) { 

//没有拿到锁就间隔interval再次尝试获取锁,直到总时间大于timeout
try { 

Thread.sleep(Double.valueOf(interval*1000).longValue());
} catch (InterruptedException e) { 

log.error("RedisUtils getLockByInterval error:",e);
}
currentTime += interval;
// 递归
return getLockByInterval(key,value,timeout,interval,currentTime);
}
return true;
}

上述代码其实还是不够完美,当并发量足够大时可能存在某线程在超时时间内还是没有抢占到锁,因为获取锁的机制是按照间隔时间来获取的,并且属于非公平锁,即不是先到的线程有权利优先获取锁,这里可以看到redis的分布式锁并不是很友好,这里再介绍下zookeeper的分布式锁

分布式锁对比

redis分布式锁:通过redis通过的sexNx命令实现,即当key不存在时调用setNx返回true,否则返回false,获取不到锁的线程只能轮询去尝试获取锁 优点:性能高,使用简单,在允许偶发锁失效的场景下推荐使用 缺点:通过轮询抢占锁的机制不是很可靠,当某线程占用锁时间较长时可能导致其他线程抢占锁失败

zookeeper分布式锁:zk的分布式锁机制是利用zk的临时有序节点,即多个线程同时抢占锁会创建多个节点如a1->a2->a3->a4->a5…,只有拿到第一个节点的线程获得锁,里面节点注册是的watch机制,即a1使用完后会释放当前节点,同时watch下一个节点a2,依次类推 优点:不依靠轮询抢占锁,依靠的是节点间的通信,比较可靠,当业务场景要求比较高是推荐使用 缺点:性能不如redis缓存锁高

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/196177.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年9月7日 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 分布式锁介绍
  • 场景介绍
  • 分布式锁对比
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档