Redis分布式锁最全详解(图文全面总结)
wptr33 2025-01-05 20:31 18 浏览
分布式锁是分布式系统的核心,也是大厂重点考察对象,下面我就全面来详解Redis分布式锁@mikechen
本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集》里面。
分布式锁
分布式锁是一种用于在分布式系统中,协调多个进程、或者多个节点,对共享资源的访问机制。
如下图所示:
多台Jboss应用服务器上的JVM,需要访问:“共享变量”,这种典型的多个进程争夺资源,就需要分布式锁来保证资源安全性。
分布式锁可以确保同一时刻,只有一个节点能够修改数据,这样可以,防止数据冲突、和不一致的发生。
要实现分布式锁,一般需要,满足如下核心关键点:
1.互斥性
在同一时刻,只有一个客户端能持有锁;
比如:使用分布式缓存系统(如:Redis)的,SETNX(SET if Not eXists)命令来创建锁。
只有当锁不存在时才能成功创建,确保了互斥性。
2.可重入性
同一个客户端可以多次获取同一把锁,必须要确保是同一个客户端。
比如:每个客户端在获取锁时,附带一个唯一的标识(如:UUID),如果同一个客户端尝试多次获取同一把锁,可以通过这个标识来判断并允许重入。
3.高可用性
锁的获取、和释放操作应该是高可用的。
比如:将锁服务部署成主备结构,当主节点失效时,备节点可以立即接管。
4.容错性
如果持有锁的客户端崩溃,锁能够被其他客户端重新获取。
比如:设置锁的自动过期时间,即使客户端崩溃,锁在过期后也能被其他客户端获取。
Redis分布式锁实现
下面,我以Redis为例,实现分布式锁:
1.获取锁
使用 SET key value NX PX milliseconds 命令:
SET my_lock_key my_lock_value NX PX 10000
参数说明:
- SET:用于设置键的值;
- my_lock_value:锁的值(value),通常是唯一的标识符,例如:UUID,用于区分锁的持有者;
- NX:表示“仅在键不存在时设置”,即如果键已经存在,则不会执行设置操作,这保证了只有一个客户端能够成功设置锁;
- PX:设置键的过期时间(以毫秒为单位),这用于防止持有锁的客户端崩溃导致的死锁问题,即使客户端崩溃,锁也会在过期后自动释放。
- PX 10000:设置锁的过期时间为10000毫秒(即:10秒),防止锁被永久占用。
2.释放锁
使用Lua脚本,可以确保锁的释放是原子操作:
脚本会检查,当前键的值是否与持锁客户端的值匹配,如果匹配则删除键;
如果不匹配,表示锁的持有者不是当前客户端,删除操作不会执行。
如下所示:
public void release() {
// 使用Lua脚本来确保释放操作的原子性
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else " +
"return 0 " +
"end";
jedis.eval(script, 1, lockKey, lockValue);
}
参数说明:
- redis.call('get', KEYS[1]):获取锁的当前值;
- == ARGV[1]:检查当前值是否与持锁客户端的值(ARGV[1])匹配;
- redis.call('del', KEYS[1]):如果匹配,则删除键,释放锁;
3.注意事项
- 过期时间:确保设置适当的过期时间,避免锁被持有太长时间导致资源被锁定。
- 错误处理:在实际应用中,需要处理可能的异常情况,例如Redis连接失败等。
- 性能优化:在高并发环境下,确保Redis服务器的性能能够满足锁的需求,并适当调整Redis配置以优化性能。
以上
本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集》里面。
相关推荐
- 一篇文章带你了解PHP的学习使用(php的教程)
-
ThinkPHP5实战...
- 在memcached管理php的session(memcached libevent)
-
PHP的session(会话管理)一般是以文件形式进行,而在多个Web服务器之间进行session管理时memecached会比文件管理方式更加方便。在这里介绍如何使用memcached管理PHP的s...
- php传值和传引用的区别(php 传值和传引用)
-
php传值:在函数范围内,改变变量值得大小,都不会影响到函数外边的变量值。PHP传引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。传值:和copy是一样的。【打个比...
- PHP 常量详解教程(php常量和变量)
-
常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常...
- php自学零基础入门小知识(php新手入门教程)
-
我们就把PHP入门当成一个苹果吧!一口一口的吃掉他!不啰嗦了!开始了1、嵌入方法:类似ASP的<%,PHP可以是<?php或者是<?,结束符号是?>,当然您也可以自己指定。2、...
- PHP 语法详解(php语法大全)
-
PHP脚本在服务器上执行,然后向浏览器发送回纯HTML结果。基础PHP语法PHP脚本可放置于文档中的任何位置。PHP脚本以<?php开头,以?>结尾:<?php...
- PHP笔记(一)PHP基础知识(php必背知识点)
-
创建PHP程序PHP代码框架<?php>2.文件命名规则...
- PHP 8新特性之Attributes(注解),你掌握了吗?
-
PHP8的Alpha版本,过几天就要发布了,其中包含了不少的新特性,当然我自己认为最重要的还是JIT,这个我从2013年开始参与,中间挫折无数,失败无数后,终于要发布的东东。不过,今天呢,我不打算谈J...
- PHP基本语法之标记与注释(php注释规范)
-
1、标记由于PHP是嵌入式脚本语言,它在实际开发中经常会与HTML内容混在一起,所以为了区分HTML与PHP代码,需要使用标记对PHP代码进行标识。如:<html>...
- php注解(PHP注解 性能)
-
目标了解和使用php注解,如果你已经掌握其他一种具有注解的语言,例如:java、python等,你在本文中只需要了解点语法就行。示例php8以前的版本,注解写在注释里,如果你掌握其他语言的注解,你是不...
- 数据丢失?别慌!MySQL备份恢复攻略
-
想象一下,某个晴朗的午后,你正享受着咖啡,突然接到紧急电话:你的网站或APP彻底挂了!系统崩溃,界面全白。虽然心头一紧,但你或许还能安慰自己:系统崩溃只是暂停服务,数据还在,修复修复就好了。然而,如果...
- MySQL 日志:undo log、redo log、binlog
-
今天来和大家分享MySQL的三个日志文件,可以说MySQL的多数特性都是围绕日志文件实现,而其中最重要的有以下三种:...
- MySQL三大日志:binlog、redolog、undolog全解析
-
binlog概述在MySQL数据库中,binlog可是个相当重要的存在,它的全称为binarylog,也就是二进制日志。它就像是数据库的“记忆本”,记录了所有的DDL(数据定义语言)和...
- 1、MySQL数据库介绍(mysql数据库简单介绍)
-
1.1数据库的核心定义数据库的本质数据库乃存储数据对象之容器,涵盖如下关键组件:表(Table)...
- MySQL 日志双雄:实时监控与历史归档实战优化
-
MySQL日志双雄:实时监控+历史归档实战用这招让你家日志系统再也不卡不爆炸MySQL十亿级日志处理:从洪峰到归档全攻略手把手教你用MySQL搞定ELK级日志监控在微服务架构大行其道的今天,日志系统早...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)