java的分布式锁

什么是分布式锁

分布式锁是指分布式环境下,系统部署在多个机器中,实现多进程分布式互斥的一种锁。为了保证多个进程能看到锁,锁被存在公共存储(比如 Redis、Memcache、数据库等三方存储中),以实现多个进程并发访问同一个临界资源,同一时刻只有一个进程可访问共享资源,确保数据的一致性。

在单机时代,虽然不存在分布式锁,但也会面临资源互斥的情况,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制,即当某个线程获取到这个资源后,就需要对这个资源进行加锁,当使用完资源之后,再解锁,其它线程就可以接着使用了。例如,在JAVA中,甚至专门提供了一些处理锁机制的一些API(synchronize/Lock等)。

但是到了分布式系统的时代,这种线程之间的锁机制,就没作用了,系统可能会有多份并且部署在不同的机器上,这些资源已经不是在线程之间共享了,而是属于进程之间共享的资源。因此,为了解决这个问题,「分布式锁」就强势登场了。

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。

在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,这个时候,便需要使用到分布式锁。

1. 分布式锁要求
  • 排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取
  • 避免死锁:这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)
  • 高可用:获取或释放锁的机制必须高可用且性能佳
2. 分布式锁实现

目前相对主流的有三种,从实现的复杂度上来看,从上往下难度依次增加:数据库(MySQL),Redis,ZooKeeper

Redisson

Redisson开源框架是一个Redis的分布式锁的现成实现方案,是Redis的 java 实现的客户端。通过 Netty 支持非阻塞 I/O。

Redisson实现了分布式锁的自动续期机制、锁的互斥自等待机制、锁的可重入加锁与释放锁的机制。

1.依赖坐标
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
2.代码示例
public String testOneLock() {
// 1.获取锁,只要锁的名字一样,获取到的锁就是同一把锁。
RLock lock = redisson.getLock("onelock");
System.out.println("-----获得锁lock对象:"+lock);
// 2.加锁
lock.lock();
try {
    System.out.println("加锁成功,执行逻辑代码。线程 ID:" + Thread.currentThread().getId());
    //while (true){
        Thread.sleep(10000);
        System.out.println("逻辑代码执行完成!。。。");
    //}
} catch (Exception e) {
    e.printStackTrace();
} finally {
    // 3.解锁
    lock.unlock();
    System.out.println("Finally处,释放锁成功。线程 ID:" + Thread.currentThread().getId());
}
return "onelock锁测试完成。";
}
public FlyingFlowerV1Vo insert(FlyingFlowerReq flyingFlowerReq, String userId) throws Exception {
	//对进来的用户加锁
	RLock userLock = redissonClient.getLock(RedissonKey.USER_ID + userId);
	try{
	    //尝试加锁, 最多等待1秒, 1000秒后自动解锁
	    if (userLock.tryLock(1, 1000, TimeUnit.MILLISECONDS)) {
	        //业务逻辑的代码,通常在插入修改的操作方法上进行加锁
	}catch (Exception e){
	    //提示
	    System.out.println("接令频繁"+ userId);
	    throw new ResultInfo(ResultUtils.error("接令频繁,请稍后再试"));
	}finally {
	    //解锁
        if (userLock.isHeldByCurrentThread()) {
            userLock.unlock();
        }
	}
	return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java分布式实现方式有多种,常见的包括: 1. 基于Redis的分布式:利用Redis单线程的特性,使用SETNX命令创建,利用EXPIRE设置的过期时间,同时使用DEL命令释放,确保的释放是原子的。 2. 基于Zookeeper的分布式:通过创建临时节点实现分布式,当某个服务占用了,其它服务将无法创建同名节点,从而保证同一时间只有一个服务占用该。 3. 基于数据库的分布式:使用数据库表中的一行记录来表示状态,使用事务确保的获取和释放是原子的。 4. 基于Redisson的分布式:Redisson是一个开源的Java分布式框架,提供了对分布式的支持,使用SETNX和EXPIRE命令实现的创建和过期,同时还提供了自旋、可重入等高级特性。 以上是Java分布式实现方式的几种常见方式,不同的实现方式有着各自的特点和适用场景,需要根据实际需求进行选择。 ### 回答2: Java分布式分布式系统中实现数据同步和控制的关键技术之一,它用于保证多个分布式进程并发访问共享资源时的数据一致性和安全性。分布式与普通的相比,需要解决跨进程、跨节点的同步和并发控制问题。 Java分布式的实现方式有以下几种: 1. 基于Zookeeper实现分布式 Zookeeper是一个高性能的分布式协调服务,它可以被用来实现分布式。Zookeeper的实现原理是基于它的强一致性和顺序性,可以保证多个进程访问同一个分布式时的数据同步和控制。 通过创建一个Zookeeper的持久节点来实现分布式,使用create()方法来创建节点,如果创建成功则说明获取成功。当多个进程同时请求获取时,只有一个进程能够创建节点成功,其它进程只能等待。当持有分布式的进程退出时,Zookeeper会自动删除对应的节点,其它进程就可以继续请求获取。 2. 基于Redis实现分布式 Redis是高性能的内存数据库,可以使用它的setnx()命令来实现分布式。setnx()命令可以在指定的key不存在时设置key的值,并返回1;如果key已经存在,则返回0。通过这个原子性的操作来实现分布式。 当多个进程同时请求获取时,只有一个进程能够成功执行setnx()命令,其它进程只能等待。进程在持有期间,可以利用Redis的expire()命令来更新的过期时间。当持有分布式的进程退出时,可以通过delete()命令来删除。 3. 基于数据库实现分布式 数据库通过ACID特性来保证数据的一致性、并发性和可靠性,可以通过在数据库中创建一个唯一索引来实现分布式。当多个进程同时请求获取时,只有一个进程能够成功插入唯一索引,其它进程只能等待。当持有分布式的进程退出时,可以通过删除索引中对应的记录来释放。 不同的实现方式各有优劣。基于Zookeeper的实现方式可以保证分布式的一致性和可靠性,但是需要引入额外的依赖;基于Redis可以实现较高性能的分布式,但是在高并发条件下可能会存在死等问题;基于数据库的实现方式简单,但在高并发条件下也可能会有争抢等问题。 总之,在选择分布式的实现方式时,需要根据业务场景和需求来综合考虑各种因素,选择最适合自己的方式。 ### 回答3: 分布式系统中的并发控制是解决分布式系统中竞争资源的重要问题之一,而分布式作为一种并发控制工具,在分布式系统中被广泛采用。Java作为一种常用的编程语言,在分布式的实现方面也提供了多种解决方案。下面就分别介绍Java分布式的实现方式。 1. 基于ZooKeeper的分布式 ZooKeeper是分布式系统中常用的协调工具,其提供了一套完整的API用于实现分布式。实现分布式的过程中需要创建一个Znode,表示,同时用于控制数据的访问。在这个Znode上注册监听器用于接收释放的成功/失败事件,从而控制加/解的过程。 2. 基于Redis的分布式 Redis作为一种高性能的Key-Value数据库,其提供了完整的API用于实现分布式。实现分布式的过程中需要在Redis中创建一个Key,利用Redis的SETNX命令进行加,同时设置过期时间保证的生命周期。在解时需要判断是否持有并删除对应的Key。 3. 基于数据库的分布式 数据库作为分布式系统中常用的数据存储方式,其提供了事务机制用于实现分布式。在实现分布式的过程中需要在数据库中创建一个表,利用数据库的事务机制实现加/解,同时需要设置过期时间保证的生命周期。 总之,以上三种方式都是常用的Java分布式的实现方式。选择合适的方法需要综合考虑的使用场景、性能需求、可靠性要求等因素。同时,在实现分布式的过程中需要注意的加/解的正确性和过期时间的设置,保证分布式系统的并发控制的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值