java分布式锁代码实现 分布式锁和jvm锁

java分布式锁的实现方式有哪些

常用的有EJB、rmi、Web Service,还有Hessian、NIO等,它们的优缺点比较比下:

成都创新互联于2013年创立,先为通化等服务建站,通化等地企业,进行企业商务咨询服务。为通化企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

1:EJB

优势:可扩展性好,安全性强,支持分布式事务处理。

劣势:不能跨语言;配置相对复杂,不同J2EE容器之间很难做无缝迁移。

2:rmi

优势:面向对象的远程服务模型;基于TCP协议上的服务,执行速度快。

劣势:不能跨语言;每个远程对象都要绑定端口,不易维护;不支持分布式事务JTA,RMI框架对于安全性、事务、可扩展性的支持非常有限。

3: Web Service

优势:跨语言、跨,SOA思想的实现;安全性高;可以用来兼容legacy系统的功能

劣势:性能相对差,不支持两阶段事务

4:Hessian

优势:使用简单,速度快;跨语言,跨;可以用来兼容legacy系统的功能。

劣势:安全性的支持不够强,不支持两阶段事务。

5:NIO(Mina/Netty)

优点:基于TCP通信,效率上高于HTTP的方式,非阻塞IO应对高并发绰绰有余。根据具体的需要制定数据传输的格式,可扩展性强。

缺点:不能跨语言,无法穿透防火墙。

复制粘贴 不喜勿喷

java怎么实现redis分布式锁

Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists。这系列的命令非常有用,这里讲使用SETNX来实现分布式锁。

用SETNX实现分布式锁

利用SETNX非常简单地实现分布式锁。例如:某客户端要获得一个名字foo的锁,客户端使用下面的命令进行获取:

SETNX lock.foo current Unix time + lock timeout + 1

如返回1,则该客户端获得锁,把lock.foo的键值设置为时间值表示该键已被锁定,该客户端最后可以通过DEL lock.foo来释放该锁。

如返回0,表明该锁已被其他客户端取得,这时我们可以先返回或进行重试等对方完成或等待锁超时。

解决死锁

上面的锁定逻辑有一个问题:如果一个持有锁的客户端失败或崩溃了不能释放锁,该怎么解决?我们可以通过锁的键对应的时间戳来判断这种情况是否发生了,如果当前的时间已经大于lock.foo的值,说明该锁已失效,可以被重新使用。

发生这种情况时,可不能简单的通过DEL来删除锁,然后再SETNX一次,当多个客户端检测到锁超时后都会尝试去释放它,这里就可能出现一个竞态条件,让我们模拟一下这个场景:

C0操作超时了,但它还持有着锁,C1和C2读取lock.foo检查时间戳,先后发现超时了。

C1 发送DEL lock.foo

C1 发送SETNX lock.foo 并且成功了。

C2 发送DEL lock.foo

C2 发送SETNX lock.foo 并且成功了。

这样一来,C1,C2都拿到了锁!问题大了!

幸好这种问题是可以避免D,让我们来看看C3这个客户端是怎样做的:

C3发送SETNX lock.foo 想要获得锁,由于C0还持有锁,所以Redis返回给C3一个0

C3发送GET lock.foo 以检查锁是否超时了,如果没超时,则等待或重试。

反之,如果已超时,C3通过下面的操作来尝试获得锁:

GETSET lock.foo current Unix time + lock timeout + 1

通过GETSET,C3拿到的时间戳如果仍然是超时的,那就说明,C3如愿以偿拿到锁了。

如果在C3之前,有个叫C4的客户端比C3快一步执行了上面的操作,那么C3拿到的时间戳是个未超时的值,这时,C3没有如期获得锁,需要再次等待或重试。留意一下,尽管C3没拿到锁,但它改写了C4设置的锁的超时值,不过这一点非常微小的误差带来的影响可以忽略不计。

注意:为了让分布式锁的算法更稳键些,持有锁的客户端在解锁之前应该再检查一次自己的锁是否已经超时,再去做DEL操作,因为可能客户端因为某个耗时的操作而挂起,操作完的时候锁因为超时已经被别人获得,这时就不必解锁了。

示例伪代码

根据上面的代码,我写了一小段Fake代码来描述使用分布式锁的全过程:

# get lock

lock = 0

while lock != 1:

timestamp = current Unix time + lock timeout + 1

lock = SETNX lock.foo timestamp

if lock == 1 or (now() (GET lock.foo) and now() (GETSET lock.foo timestamp)):

break;

else:

sleep(10ms)

# do your job

do_job()

# release

if now() GET lock.foo:

DEL lock.foo

是的,要想这段逻辑可以重用,使用python的你马上就想到了Decorator,而用Java的你是不是也想到了那谁?AOP + annotation?行,怎样舒服怎样用吧,别重复代码就行。

Springboot使用redis的setnx和getset实现并发锁、分布式锁

在日常开发中,很多业务场景必须保证原子性。举几个例子:

如果你只有一台服务器,只运行一个Java程序,那么可以使用Java语言自身的一些锁来实现原子性。但如果我们有多台服务器,甚至不同服务器上跑的是不同的语言。那这时候,我们就需要一个跨平台、跨语言的加锁方式。redis就是其中最方便的一种。

使用redis实现并发锁,主要是靠两个redis的命令:setnx和getset。

那我们的设计思路就是:

上面的代码使用了一个RedisService的类,里面主要是简单封装了一下redis的操作,你可以替换为自己的service。代码如下:

以上代码有任何疑问,可以点击右侧边栏联系作者。收费5毛~交个朋友,欢迎来撩!

版权声明:《Springboot使用redis的setnx和getset实现并发锁、分布式锁》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:

java trylock能实现分布式锁吗

一、zookeeper

1、实现原理:

基于zookeeper瞬时有序节点实现的分布式锁,其主要逻辑如下(该图来自于IBM网站)。大致思想即为:每个客户端对某个功能加锁时,在zookeeper上的与该功能对应的指定节点的目录下,生成一个唯一的瞬时有序节点。判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。

二、memcached分布式锁

1、实现原理:

memcached带有add函数,利用add函数的特性即可实现分布式锁。add和set的区别在于:如果多线程并发set,则每个set都会成功,但最后存储的值以最后的set的线程为准。而add的话则相反,add会添加第一个到达的值,并返回true,后续的添加则都会返回false。利用该点即可很轻松地实现分布式锁。

三、redis分布式锁

redis分布式锁即可以结合zk分布式锁锁高度安全和memcached并发场景下效率很好的优点,可以利用jedis客户端实现


当前标题:java分布式锁代码实现 分布式锁和jvm锁
网页路径:http://ybzwz.com/article/doeiedi.html