RedLock

分布式锁全网最详解!!

断了今生、忘了曾经 提交于 2020-11-02 07:11:58
什么是锁? 在单进程的系统中,当存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量。 而同步的本质是通过锁来实现的。为了实现多个线程在一个时刻同一个代码块只能有一个线程可执行,就需要在某个地方做个标记,这个标记必须每个线程都能看到,当标记不存在时可以设置该标记,其余后续线程发现已经有标记了,则等待拥有标记的线程结束同步代码块(取消标记)后再去尝试设置标记。这个标记就可以理解为锁。 不同地方实现锁的方式并不太一样,只要能满足所有线程都能看得到标记即可。如 Java 中 synchronize 是在对象头设置标记,Lock 接口的实现类基本上都只是某一个 volitile 修饰的 int 型变量,其保证每个线程都能拥有对该 int变量 的可见性和原子修改,linux 内核中也是利用互斥量或信号量等内存数据做标记。 除了利用内存数据做锁之外,其实任何互斥的都能做锁(只考虑互斥情况),如流水表中流水号与时间结合做幂等校验可以看作是一个不会释放的锁,或者使用某个文件是否存在作为锁等。只需要满足在对标记进行修改能保证原子性和内存可见性即可。 什么是分布式? 分布式的 CAP 理论告诉我们: 任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性

集群多JVM分布式锁实现

我怕爱的太早我们不能终老 提交于 2020-10-20 06:52:18
基于数据库表乐观锁 (基本废弃) 要实现分布式锁,最简单的⽅方式可能就是直接创建⼀一张锁表,然后通过操作该表中的数据来实现了了。 当我们要锁住某个⽅法或资源时,我们就在该表中增加一条记录,想要释放锁的时候就删除这条记录。 比如创建这样一张数据库表: CREATE TABLE `methodLock` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `method_name` varchar(64) NOT NULL DEFAULT '' COMMENT '锁定的⽅方法名', `desc` varchar(1024) NOT NULL DEFAULT '备注信息', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '保存数据时间,⾃自动⽣生成', PRIMARY KEY (`id`), UNIQUE KEY `uidx_method_name` (`method_name `) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='锁定中的⽅方法'; 当我们想要锁住某个方法时,执行以下SQL: insert into

分布式概念简单了解:数据一致性、CAP、BASE、分布式事务、分布式锁

旧城冷巷雨未停 提交于 2020-08-17 09:55:18
分布式概念简单了解:数据一致性、CAP、BASE、分布式事务、分布式锁 版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 今天对分布式相关的一些概念与理论进行学习。 1.集群与分布式 集群 :相同的应用部署在多台服务器。 分布式 :不同的应用部署在多台服务器。 1.数据一致性 在分布式环境中,为了提高系统整体性能,数据以多副本冗余机制存储,副本之间通过数据复制进行同步。 数据副本与数据复制必然引入新的问题:如何处理副本数据的一致性? 总的来说,无法找到一种能够满足所有分布式环境的一致性解决方案,很多时候要在系统性能与数据一致性之间权衡。 由此,分布式一致性常见以下三种一致性: 1.1.强一致性 强一致性 :数据写以后,任意时刻,所有数据副本中的数据都是一致的。 强一致性,也可以称为:原子一致性、线性一致性。 强一致性,是非分布式环境中主要被采用的一致性原则。 在非分布式环境中,数据可以集中存储,例如整个系统就一个数据库,这种情况下容易保证数据的强一致性。 在分布式环境中,数据存在多个副本,分布在不同的服务器上,数据副本之间的同步会经过网络通讯,这种情况下,很难保证强一致性。 1.2.顺序一致性 顺序一致性 :任何一次读都能读取到数据的最近一次写的数据,系统的所有进程的顺序一致,而且是合理的。 顺序一致性,其实本人接触也不多

如何正确使用redis分布式锁

ⅰ亾dé卋堺 提交于 2020-08-16 15:21:18
前言   笔者在公司担任技术面试官,在笔者面试过程中,如果面试候选人提到了reids分布式锁,笔者都会问一下redis分布式锁的知识点,但是令笔者遗憾的是,该知识点十个人中有九个人都答得不清楚,或者回答错误,这让笔者有了写这篇文章的想法,来帮助童鞋们正确认识reids分布式锁. 什么是分布式锁?为什么需要分布式锁?   在java中,在单进程多线程的情况下,为了防止多个线程共同竞争同一个资源,因此需要锁,java中有显示锁和隐式锁来保证,而在多进程的情况下,普通的锁就无法满足要求了,因此我们需要分布式锁,常用的分布式锁解决方案有三种,分别是基于数据库/redis/zookeeper,本文我们主要讨论redis分布式锁. redis分布式锁实现   笔者在面试过程中,问redis分布式锁知识点时的第一个问题就是如何实现一个redis分布式锁,许多候选人直接说,啊,这很简单啊,使用setNx()方法,设置一个过期时间就可以了,我接着问,那如何释放锁锁呢?候选人回答说,那很简单啊,直接调用delete方法就可以了,我接着问,释放锁直接调用delete方法就可以了吗?候选人回答,对啊,delete方法也是线程安全的,我.....那么如何实现一个redis分布式锁,我们用代码来演示一下,首先来看一下加锁的代码片段:   首先我们的分布式锁实现了Lock接口,然后主要看我们的lock方法

不用找了,基于 Redis 的分布式锁实战来了!

十年热恋 提交于 2020-08-16 10:22:52
作者:菜蚜 my.oschina.net/wnjustdoit/blog/1606215 前言:在分布式环境中,我们经常使用锁来进行并发控制,锁可分为乐观锁和悲观锁, 基于数据库版本戳的实现是乐观锁,基于redis或zookeeper的实现可认为是悲观锁了。乐观锁和悲观锁最根本的区别在于线程之间是否相互阻塞。 那么,本文主要来讨论基于redis的分布式锁算法问题。 从2.6.12版本开始,redis为SET命令增加了一系列选项(set [key] NX/XX EX/PX [expiration]): 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

redis实现分布式锁

大兔子大兔子 提交于 2020-08-13 14:09:29
一、分布式锁简介 锁 是一种用来解决多个执行线程 访问共享资源 错误或数据不一致问题的工具。 如果 把一台服务器比作一个房子 ,那么 线程就好比里面的住户 ,当他们想要共同访问一个共享资源,例如厕所的时候,如果厕所门上没有锁...更甚者厕所没装门...这是会出原则性的问题的.. 装上了锁,大家用起来就安心多了,本质也就是 同一时间只允许一个住户使用 。 而随着互联网世界的发展,单体应用已经越来越无法满足复杂互联网的高并发需求,转而慢慢朝着分布式方向发展,慢慢进化成了 更大一些的住户 。所以同样,我们需要引入分布式锁来解决分布式应用之间访问共享资源的并发问题。 为何需要分布式锁 一般情况下,我们使用分布式锁主要有两个场景: 避免不同节点重复相同的工作 :比如用户执行了某个操作有可能不同节点会发送多封邮件; 避免破坏数据的正确性 :如果两个节点在同一条数据上同时进行操作,可能会造成数据错误或不一致的情况出现; Java 中实现的常见方式 上面我们用简单的比喻说明了锁的本质: 同一时间只允许一个用户操作 。所以理论上,能够满足这个需求的工具我们都能够使用 (就是其他应用能帮我们加锁的) : 基于 MySQL 中的锁 :MySQL 本身有自带的悲观锁 for update 关键字,也可以自己实现悲观/乐观锁来达到目的; 基于 Zookeeper 有序节点 :Zookeeper

如何设计高性能的分布式锁

落爺英雄遲暮 提交于 2020-08-12 15:19:02
什么是分布式锁? ​ 在 JVM 中,在多线程并发的情况下,我们可以使用同步锁或 Lock 锁,保证在同一时间内,只能有一个线程修改共享变量或执行代码块。但现在我们的服务都是基于分布式集群来实现部署的,对于一些共享资源,在分布式环境下使用 Java 锁的方式就失去作用了。 ​ 使用数据库实现一个分布式锁比较简单易懂,直接基于数据库实现就行了,不需要再引入第三方中间件,所以这是很多分布式业务实现分布式锁的首选。但是数据库实现的分布式锁在一定程度上,存在性能瓶颈,所以我推荐使用Redis。 Redis 实现分布式锁 ​ Redis 实现分布式锁的方式,是使用 SETNX+EXPIRE 组合来实现,在 Redis 2.6.12 版本之前,具体实现代码如下: public static boolean tryLock(Jedis jedis, String lockKey, String requestId, int expireTime) { Long result = jedis.setnx(lockKey, requestId);//设置锁 if (result == 1) {//获取锁成功 // 若在这里程序突然崩溃,则无法设置过期时间,将发生死锁 jedis.expire(lockKey, expireTime);//通过过期时间删除锁 return true; } return

【分布式缓存系列】集群环境下Redis分布式锁的正确姿势

蹲街弑〆低调 提交于 2020-08-12 06:13:54
一、前言   在上一篇文章中,已经介绍了基于Redis实现分布式锁的正确姿势,但是上篇文章存在一定的缺陷——它加锁只作用在一个Redis节点上,如果通过sentinel保证高可用,如果master节点由于某些原因发生了主从切换,那么就会出现锁丢失的情况: 客户端1在Redis的master节点上拿到了锁 Master宕机了,存储锁的key还没有来得及同步到Slave上 master故障,发生故障转移,slave节点升级为master节点 客户端2从新的Master获取到了对应同一个资源的锁   于是,客户端1和客户端2同时持有了同一个资源的锁。锁的安全性被打破了。针对这个问题。Redis作者antirez提出了RedLock算法来解决这个问题 二、RedLock算法的实现思路   antirez提出的redlock算法实现思路大概是这样的。   客户端按照下面的步骤来获取锁: 获取当前时间的毫秒数T1。 按顺序依次向N个Redis节点执行获取锁的操作。这个获取锁的操作和上一篇中基于单Redis节点获取锁的过程相同。包括唯一UUID作为Value以及锁的过期时间(expireTime)。为了保证在某个在某个Redis节点不可用的时候算法能够继续运行,这个获取锁的操作还需要一个超时时间。它应该远小于锁的过期时间。客户端向某个Redis节点获取锁失败后,应立即尝试下一个Redis节点

分布式锁用 Redis 还是 Zookeeper?

家住魔仙堡 提交于 2020-08-10 07:22:46
云栖号资讯:【 点击查看更多行业资讯 】 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 为什么用分布式锁? 在讨论这个问题之前,我们先来看一个业务场景: 系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户下单。 由于系统有一定的并发,所以会预先将商品的库存保存在redis中,用户下单的时候会更新redis的库存。 此时系统架构如下: 但是这样一来会产生一个问题:假如某个时刻,redis里面的某个商品库存为1,此时两个请求同时到来,其中一个请求执行到上图的第3步,更新数据库的库存为0,但是第4步还没有执行。 而另外一个请求执行到了第2步,发现库存还是1,就继续执行第3步。 这样的结果,是导致卖出了2个商品,然而其实库存只有1个。 很明显不对啊!这就是典型的库存超卖问题 此时,我们很容易想到解决方案:用锁把2、3、4步锁住,让他们执行完之后,另一个线程才能进来执行第2步。 按照上面的图,在执行第2步时,使用Java提供的synchronized或者ReentrantLock来锁住,然后在第4步执行完之后才释放锁。” 这样一来,2、3、4 这3个步骤就被“锁”住了,多个线程之间只能串行化执行。 但是好景不长,整个系统的并发飙升,一台机器扛不住了。现在要增加一台机器,如下图:

面试被问 Redis 锁,我哭了 qaq

落花浮王杯 提交于 2020-07-25 14:34:10
谈起redis锁,下面三个,算是出现最多的高频词汇: setnx redLock redisson setnx 其实目前通常所说的setnx命令,并非单指redis的setnx key value这条命令。 一般代指redis中对set命令加上nx参数进行使用, set这个命令,目前已经支持这么多参数可选: SET key value [EX seconds|PX milliseconds] [NX|XX] [KEEPTTL] 当然了,就不在文章中默写Api了,基础参数还有不清晰的,可以蹦到官网。 上图是笔者画的setnx大致原理,主要依托了它的key不存在才能set成功的特性,进程A拿到锁,在没有删除锁的Key时,进程B自然获取锁就失败了。 那么为什么要使用PX 30000去设置一个超时时间? 是怕进程A不讲道理啊,锁没等释放呢,万一崩了,直接原地把锁带走了,导致系统中谁也拿不到锁。 就算这样,还是不能保证万无一失。 如果进程A又不讲道理,操作锁内资源超过笔者设置的超时时间,那么就会导致其他进程拿到锁,等进程A回来了,回手就是把其他进程的锁删了,如图: 还是刚才那张图,将T5时刻改成了锁超时,被redis释放。 进程B在T6开开心心拿到锁不到一会,进程A操作完成,回手一个del,就把锁释放了。 当进程B操作完成,去释放锁的时候(图中T8时刻): 找不到锁其实还算好的