RedLock

分布式锁的实现分析

谁说胖子不能爱 提交于 2019-12-12 21:47:47
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1、设计目标 分布式部署的应用集群中保证数据更新的互斥性,且程序出现异常时,锁能够自动释放,避免死锁发生。 2、为什么要使用分布式锁 为了保证分布式部署的应用集群中同一时间只有一个客户端对共享资源进行操作。根据锁的用途再细分: 对共享资源的操作是幂等性的,使用分布式锁能够避免重复操作,从而提高效率。 对共享资源的操作是非幂等的,比如订单状态的修改,如果多个客户端同时操作,最后的结果可能很遭,使用分布式锁可以让各个客户端分散时间操作。 3、分布式锁应具备哪些条件 这也是分布式锁的关键技术。 互斥性 这个是分布式锁的基本要求,分布式锁需要保证不同客户端的不同线程之间互斥。 可重入性 支持锁的重入,减少资源消耗。 锁超时释放 获取锁的客户端因为某些原因而宕机,而未能释放锁,其他客户端无法获取此锁,锁超时释放是为了避免死锁。 安全性 锁只能被持有该锁的用户删除,而不能被其他用户删除。 高效与高可用 加锁与解锁需要高效,并保证高可用,当部分节点宕机,客户端仍能获取锁或者释放锁。 支持阻塞与非阻塞 阻塞就是线程获取不到锁一直阻塞,增加超时时间可以防止一直阻塞。非阻塞则获取不到锁不阻塞线程。 支持公平与非公平 公平锁就是按照加锁的顺序获取到锁,非公平锁即无序。 4、基于Redis 4.1、 从一个问题开始 问题

分布式锁

為{幸葍}努か 提交于 2019-12-09 11:48:19
分布式锁 在叙述分布式锁前,先对锁的原理进行理解。 如何避免竞争条件 两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件。——《现代操作系统》 而锁正是避免竞争条件的解决方案之一。 再列出《现代操作系统》一书中,要成为一个解决竞争条件的好方案的条件: 任何两个进程不能同时处于其临界区 不应对 CPU 的速度和数量做任何假设 临界区外运行的进程不得阻塞其他进程 不得使进程无限期等待进入临界区 互斥量 互斥量是构建锁的一个基础原理。 互斥量是一个可以处于两态之一的变量:解锁和加锁。如,用 0 表示解锁,其他值表示加锁。当一个线程或是进程需要访问临界区时,如果互斥量当前是解锁状态,即线程可以自由进入临界区,并更改互斥量的值,当然这个过程需要是原子性的。 如果互斥量已经加锁,调用线程被阻塞,直到获得锁的线程将互斥量重置。 而我们平时使用的 java 的 ReentrantLock 也是基于互斥量的原理,使用 CAS 更新互斥量,更新成功即获得锁,否则进入阻塞。 根据互斥量的定义和 ReentrantLock 的实现原理,这里总结一下互斥量的性质: 互斥量状态判断到变更的过程必须是原子性的 当无法获取互斥量时返回,无法进入临界区 对于如 ReentrantLock 的实现,如果获取不了锁,会阻塞线程,其实就是无法获取互斥量时返回并进行线程阻塞,等待解锁。

分布式锁

笑着哭i 提交于 2019-12-08 17:13:37
分布式锁 在叙述分布式锁前,先对锁的原理进行理解。 如何避免竞争条件 两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件。——《现代操作系统》 而锁正是避免竞争条件的解决方案之一。 再列出《现代操作系统》一书中,要成为一个解决竞争条件的好方案的条件: 任何两个进程不能同时处于其临界区 不应对 CPU 的速度和数量做任何假设 临界区外运行的进程不得阻塞其他进程 不得使进程无限期等待进入临界区 互斥量 互斥量是构建锁的一个基础原理。 互斥量是一个可以处于两态之一的变量:解锁和加锁。如,用 0 表示解锁,其他值表示加锁。当一个线程或是进程需要访问临界区时,如果互斥量当前是解锁状态,即线程可以自由进入临界区,并更改互斥量的值,当然这个过程需要是原子性的。 如果互斥量已经加锁,调用线程被阻塞,直到获得锁的线程将互斥量重置。 而我们平时使用的 java 的 ReentrantLock 也是基于互斥量的原理,使用 CAS 更新互斥量,更新成功即获得锁,否则进入阻塞。 根据互斥量的定义和 ReentrantLock 的实现原理,这里总结一下互斥量的性质: 互斥量状态判断到变更的过程必须是原子性的 当无法获取互斥量时返回,无法进入临界区 对于如 ReentrantLock 的实现,如果获取不了锁,会阻塞线程,其实就是无法获取互斥量时返回并进行线程阻塞,等待解锁。

基于redis的分布式锁的分析与实践

有些话、适合烂在心里 提交于 2019-12-06 19:56:45
前言:在分布式环境中,我们经常使用锁来进行并发控制,锁可分为乐观锁和悲观锁,基于数据库版本戳的实现是乐观锁,基于redis或zookeeper的实现可认为是悲观锁了。乐观锁和悲观锁最根本的区别在于线程之间是否相互阻塞。 那么,本文主要来讨论基于redis的分布式锁算法问题。 从2.6.12版本开始,redis为 SET 命令增加了一系列选项(SET key value [EX seconds] [PX milliseconds] [NX|XX]): EX seconds – 设置键key的过期时间,单位时秒 PX milliseconds – 设置键key的过期时间,单位时毫秒 NX – 只有键key不存在的时候才会设置key的值 XX – 只有键key存在的时候才会设置key的值 原文地址: https://redis.io/commands/set 中文地址: http://redis.cn/commands/set.html 注意: 由于 SET 命令加上选项已经可以完全取代 SETNX , SETEX , PSETEX 的功能,所以在将来的版本中,redis可能会不推荐使用并且最终抛弃这几个命令。 (这里简单提一下,在旧版本的redis中(指2.6.12版本之前),使用redis实现分布式锁一般需要setNX、expire、getSet、del等命令

Redisson实现分布式锁及其底层原理解析

社会主义新天地 提交于 2019-12-04 05:31:58
目前主流的开源解决方案有jedis,redission,lettuce三种解决方案,其中jedis是同步的方案,现在包括spring-data也已经不再内置使用了,替换成了lettuce。redission和lettuce都是基于netty的也就是说他俩都是异步非阻塞的,但是他们有什么区别呢?其实在使用语法上面有一些区别,redission对结果做了一层包装,通过包装类来进行一些额外的操作来达到异步操作,并且redission提供了额外的分部署锁功能。 Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比, 功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离, 从而让使用者能够将精力更集中地放在处理业务逻辑上。 Jedis使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。 Redisson使用非阻塞的I/O和基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。 一