Redis分布式锁

Redis分布式锁 一、 Redis锁基础概念 1. 为什么需要Redis锁 Redis锁是一种基于内存数据库Redis实现的分布式锁机制,主要解决分布式系统中的资源竞争问题。相比数据库锁,Redis锁具有以下优势 高性能:基于内存操作,响应速度快 原子性保证:Redis单线程模型天然支持原子操作 分布式支持:可跨多台服务器使用 丰富的数据结构:支持多种锁实现方式 2. 基本实现原理 最简单的Redis锁实现方式: SET resource_name my_random_value NX PX 30000 NX:仅当key不存在时设置 PX:设置过期时间(毫秒) my_random_value:唯一标识,用于安全释放锁 二、Redis锁的实现方式 1. SETNX实现(基本方式) 实现步骤: 尝试获取锁:SETNX lock_key 1 获取成功则设置过期时间:EXPIRE lock_key 30 执行业务逻辑 释放锁:DEL lock_key 问题: 非原子操作,SETNX和EXPIRE之间可能崩溃导致死锁 2. SET扩展参数实现(推荐) Redis 2.6.12+版本支持扩展参数,可原子性完成设置 SET lock_key unique_value NX PX 30000 PHP实现示例: $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $lockKey = 'order_lock_123'; $uniqueId = uniqid(); $expire = 30000; // 30秒 // 尝试获取锁 $acquired = $redis->set($lockKey, $uniqueId, ['NX', 'PX' => $expire]); if ($acquired) { try { // 执行业务逻辑 processOrder(); } finally { // 使用Lua脚本保证原子性释放 $script = " if redis....

2024年04月23日 · 3 min · Leanku

Redis高可用

Redis高可用 1. 事务机制和IO多路复用 1.1 事务 1.1.1 事务特点 事务提交前,先检查命令语法是否正确 提交后的命令一定会执行 有命令报错,也会执行完 不能回滚 1.1.2 命令 multi,告诉Redis服务器开启一个事务。只是开启而不是执行。 exec, 告诉Redis开始执行事务 discard,告诉Redis取消事务 watch,监视某一个键值对,它的作用是在事务执行之前如果监视的键值被修改,事务会被取消 1.2 IO多路复用 redis 是单线程,单线程只能在一个CPU内核上执行,假如是4核的,只会占用一个,其它三个不参与。 worker线程串行 read读->计算->write返回 在Redis6.0加入了io-threads, 主线程worker只进行计算,并行读取 io-threads 4 io-threads-do-reads yes 2. 持久化和过期淘汰策略 2.1 持久化 Redis是存储在内存中的, 服务器重启数据会丢失。持久化方案可以保存数据到磁盘文件,可以恢复到内存中。Redis提供的持久化方案有: rdb:生成某一时刻的快照,保存到二进制文件中 优点: 容灾性好,方便备份 性能最大化,fork出一个子进程来操作,对主进程没有影响 数据较多时,相对于aof启动效率更高 缺点: 会造成数据丢失 aof:实时记录每一条写命令,追加到文件中,打开可以看到具体的操作记录 同步策略:appendfsync everysec(默认),每秒同步一次 always,每次操作后都要同步一次 no,由操作系统调度进行同步 重写策略: 手动触发,执行bgrewiteaof命令 自动触发:auto-rewrite-percentage 100, auto-rewrite-min-size 64mb 优点 数据安全,不会造成数据的丢失 缺点 比rdb重启效率低;运行效率比rdb低 混合模式:上面两种方式的结合 触发方式有两种: 手动触发: save命令,会让Redis处于阻塞的状态,直到rdb持久化完成,线上环境谨慎使用 bgsave命令,它会fork出一个子进程(有短暂阻塞),用来执行持久化,主进程继续响应客户端请求 自动触发: 配置文件修改(save n m),在n秒内,有m个key发生变化就会触发,执行命令最总执行的是bgsave 2.2 过期键删除策略 Redis设置key时,都会设置一个过期时间,Redis同时使用了两种过期删除策略,惰性过期和定时过期...

2024年04月23日 · 1 min · Leanku

分布式session

分布式session 在单体服务器的年代,Session 直接保存在服务器中,是没有问题的,而且实现起来很容易。 但是随着分布式架构的流行,单个服务器已经不能满足系统的需要了,通常都会把系统部署在多台服务器上,通过负载均衡把请求分发到其中的一台服务器上; 那么很有可能第一次请求访问的 A 服务器,创建了 Session ,但是第二次访问到了 B 服务器,这时就会出现取不到 Session 的情况; 于是,分布式架构中,Session 共享就成了一个很大的问题。 解决方案 1. session同步 思路:多个web-server之间相互同步session,这样每个web-server之间都包含全部的session 优点:web-server支持的功能,应用程序不需要修改代码 不足: 1.session的同步需要数据传输,占内网带宽,有时延。 2.所有web-server都包含所有session数据,数据量受内存限制,无法水平扩展。 3.主从架构固有的保证一致性会牺牲可用性的特定,但进行主从同步时,登陆的请求将被阻塞,显然不符合用户实际需求。 2. 客户端存储法 思路:服务端存储所有用户的session,内存占用较大,可以将session存储到浏览器cookie中 优点:服务端不需要存储 缺点: 1.每次http请求都携带session,占外网带宽 2.数据存储在端上,并在网络传输,存在泄漏、篡改、窃取等安全隐患 3.session存储的数据大小受cookie限制 “端存储”的方案虽然不常用,但确实是一种思路。 3. 反向代理hash一致性 思路:使用 Nginx (或其他复杂均衡软硬件)中的 IP 绑定策略,同一个 IP 只能在指定的同一个机器访问,但是这样做失去了负载均衡的意义,当挂掉一台服务器的时候,会影响一批用户的使用,风险很大; 反向代理层做逻辑处理 方案一:ip进行hash 反向代理层使用用户ip来做hash,以保证同一个ip的请求落在同一个web-server上. 方案二:含有业务属性的字段hash 反向代理使用http协议中的某些业务属性来做hash,例如sid,city_id,user_id等,能够更加灵活的实施hash策略,以保证同一个浏览器用户的请求落在同一个web-server(即不同的user_id对应不同的web-server). 总结:让专业的软件做专业的事情,反向代理就负责转发,尽量不要引入应用层业务属性,除非不得不这么做(例如,有时候多机房多活需要按照业务属性路由到不同机房的web-server)。 4. 后端统一集中存储(主流方案) 思路:将session存储在web-server后端的存储层,数据库或者缓存 优点: 1.没有安全隐患 2.可以水平扩展,数据库/缓存水平切分即可,可以存储较多的session。 3.web-server重启或者扩容都不会有session丢失 不足:增加了一次网络调用,并且需要修改应用代码。 对于db存储还是cache,个人推荐后者:session读取的频率会很高,数据库压力会比较大。 如果有session高可用需求,cache可以做高可用,但大部分情况下session可以丢失,一般也不需要考虑高可用。

2024年04月21日 · 1 min · Leanku

NGINX负载均衡

NGINX负载均衡 Nginx是一个强大的开源Web服务器和反向代理服务器,它支持正向代理和反向代理功能。 正向代理 正向代理是客户端访问代理服务器去访问目标服务器,并且对目标服务器隐藏了客户端的真实信息(IP等信息) 正向代理的主要用途包括: 访问被限制的资源:当某些资源受到网络限制或访问限制时,可以使用正向代理绕过这些限制来获取资源。 提高访问速度:代理服务器可以缓存经常请求的资源,从而提高客户端访问资源的速度。 突破防火墙:正向代理可以帮助绕过企业或国家防火墙的限制,访问被封锁的网站或资源。 反向代理 反向代理是指代理服务器接收客户端的请求,然后反向代理将客户端的请求分发给一个或多个目标服务器,最后将响应返回给客户端,对于客户端隐藏了真实的服务端信息 反向代理的主要用途包括: 负载均衡:反向代理可以根据一定的算法将请求均匀地分发给后端的多台服务器,从而实现负载均衡,提高系统的并发处理能力和稳定性。 缓存静态资源:反向代理可以缓存经常请求的静态资源,减少后端服务器的负载,提高网站的访问速度。 安全性和可靠性:反向代理可以作为防火墙和安全设备,提供安全认证、访问控制、DDoS攻击防护等功能。 Nginx配置文件 #user nobody; 是用来指定 Nginx 进程运行的用户和用户组的配置项。 在 Linux 系统中,各个进程需要以某个用户的身份来运行,以限制权限并提高安全性 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 8080; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } 第一部分 全局块worker_processes:...

2024年04月20日 · 3 min · Leanku

Redis主从复制

Redis主从复制 一、什么是Redis主从复制 1. 从复制的架构: Redis Replication是一种 master-slave 模式的复制机制,这种机制使得 slave 节点可以成为与 master 节点完全相同的副本,可以采用一主多从或者级联结构。 主从复制的配置要点: 配从库不配主,从库配置:slaveof 主库IP 主库端口 查看redis的配置信息:info replication 2. Redis为什么需要主从复制? 使用Redis主从复制的原因主要是单台Redis节点存在以下的局限性: Redis虽然读写的速度都很快,单节点的Redis能够支撑QPS大概在5w左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。 单节点的Redis不能保证高可用,当Redis因为某些原因意外宕机时,会导致缓存不可用 CPU的利用率上,单台Redis实例只能利用单个核心,这单个核心在面临海量数据的存取和管理工作时压力会非常大。 3. 主从复制的好处: 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。 故障恢复:如果master宕掉了,使用哨兵模式,可以提升一个 slave 作为新的 master,进而实现故障转移,实现高可用 负载均衡:可以轻易地实现横向扩展,实现读写分离,一个 master 用于写,多个 slave 用于分摊读的压力,从而实现高并发; 4. 主从复制的缺点: 由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave服务器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重 二、主从复制的原理 从总体上来说,Redis主从复制的策略就是:当主从服务器刚建立连接的时候,进行全量同步;全量复制结束后,进行增量复制。当然,如果有需要,slave 在任何时候都可以发起全量同步。 1、主从全量复制的流程: Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份,具体步骤如下: slave服务器连接到master服务器,便开始进行数据同步,发送psync命令(Redis2.8之前是sync命令) master服务器收到psync命令之后,开始执行bgsave命令生成RDB快照文件并使用缓存区记录此后执行的所有写命令 如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是每个连接都执行一次,然后再把这一份持久化的数据发送给多个并发连接的slave。 如果RDB复制时间超过60秒(repl-timeout),那么slave服务器就会认为复制失败,可以适当调节大这个参数 master服务器bgsave执行完之后,就会向所有Slava服务器发送快照文件,并在发送期间继续在缓冲区内记录被执行的写命令 client-output-buffer-limit slave 256MB 64MB 60,如果在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么停止复制,复制失败 slave服务器收到RDB快照文件后,会将接收到的数据写入磁盘,然后清空所有旧数据,在从本地磁盘载入收到的快照到内存中,同时基于旧的数据版本对外提供服务。 master服务器发送完RDB快照文件之后,便开始向slave服务器发送缓冲区中的写命令 slave服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令; 如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF 2、增量复制: Redis的增量复制是指在初始化的全量复制并开始正常工作之后,master服务器将发生的写操作同步到slave服务器的过程,增量复制的过程主要是master服务器每执行一个写命令就会向slave服务器发送相同的写命令,slave服务器接收并执行收到的写命令。 3、断点续传: 什么是断点续传: 当master-slave网络连接断掉后,slave重新连接master时,会触发全量复制,但是从2.8版本开始,slave与master能够在网络连接断开重连后,只从中断处继续进行复制,而不必重新同步,这就是所谓的断点续传。 断电续传这个新特性使用psync命令,旧的实现中使用sync命令。Redis2.8版本可以检测出它所连接的服务器是否支持PSYNC命令,不支持的话使用SYNC命令。master服务器收到slave发送的psync命令后,会根据自身的情况做出对应的处理,可能是FULLRESYNC runid offset触发全量复制,也可能是CONTINUE触发增量复制 命令格式:psync runid offset 工作原理:...

2024年03月20日 · 2 min · Leanku

Linux常用命令

Linux基本简介 Linux 是一个基于Linux 内核的开源类Unix 操作系统,Linus Torvalds于 1991 年 9 月 17 日首次发布的操作系统内核。Linux 通常打包为Linux 发行版。 Linux文件系统 Linux一切皆文件 只有一个顶级目录,不像windows分C盘、D盘、E盘 Linux 含义 windows /bin 所有用户可用的基本命令存放的位置 windows没有固定的命令存放目录 /sbin 需要管理员权限才能使用的命令 /boot linux系统启动的时候需要加载和使用的文件 /dev 外设连接linux后,对应的文件存放的位置 类似Windows中的U盘,光盘的符号文件。 /etc 存放系统或者安装的程序的配置文件,注册服务等 类似windows中的注册表, /home 家目录,linux中每新建一个用户,会自动在home中为该用户分配一个文件夹 类似windows中的"我的文档",每个用户有自己的目录。 /root root账户的家目录,仅供root账户使用 类似windows中的Administrator账户的"我的文档" /lib linux的命令和系统启动,需要使用一些公共的依赖,放在lib中,类似我们开发的代码执行需要引入的jdk的jar /usr 很多系统软件的默认安装路径 类似windows中的C盘下的Program Files目录。 /var 系统和程序运行产生的日志文件和缓存文件放在这里 Linux常用命令 命令格式 :命令 [-选项] [参数] 例 : ls -la /etc 文件管理 命令 解释 参数 示例 ls 列出目录的内容 -a 显示所有文件,包括隐藏文件; -l详细信息显示; -d 查看目录属性 ls -la cd 切换工作目录 cd ....

2024年03月18日 · 2 min · Leanku

​MySQL优化常用方法

​MySQL优化常用方法 1. EXPLAIN EXPLAIN 查看SQL执行计划 主要字段说明: type列,连接类型。一个好的SQL语句至少要达到range级别。杜绝出现all级别。 key列,使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式。 key_len列,索引长度。 rows列,扫描行数。该值是个预估值。 extra列,详细说明。注意,常见的不太友好的值,如下:Using filesort,Using temporary。 2. SQL语句中IN包含的值不应过多 MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from t where num in(1,2,3) 对于连续的数值,能用between就不要用in了;再或者使用连接来替换。 3. SELECT语句务必指明字段名称 SELECT*增加很多不必要的消耗(CPU、IO、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前断也需要更新。所以要求直接在select后面接上字段名。 4. 当只需要一条数据的时候,使用limit 1 这是为了使EXPLAIN中type列达到const类型 5. 如果排序字段没有用到索引,就尽量少排序 6. 如果限制条件中其他字段没有索引,尽量少用or or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用union all或者是union(必要的时候)的方式来代替“or”会得到更好的效果。 7. 尽量用union all代替union nion和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据。 8. 不使用ORDER BY RAND() select id from dynamic order by rand() limit 1000; 上面的SQL语句,可优化为: select id from dynamic t1 join (select rand() * (select max(id) from dynamic) as nid) t2 on t1....

2024年03月17日 · 2 min · Leanku

PHP中的设计模式

PHP中的设计模式 介绍 设计模式:提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题。设计模式并不一定就是一个类库或者第三方框架,它们更多的表现为一种思想并且广泛地应用在系统中。它们也表现为一种模式或者模板,可以在多个不同的场景下用于解决问题。设计模式可以用于加速开发,并且将很多大的想法或者设计以一种简单地方式实现。当然,虽然设计模式在开发中很有作用,但是千万要避免在不适当的场景误用它们。 分类 按照目的分,目前常见的设计模式主要有23种,根据使用目标的不同可以分为以下三大类: 创建设计模式(Creational Patterns)(5种):用于创建对象时的设计模式。更具体一点,初始化对象流程的设计模式。当程序日益复杂时,需要更加灵活地创建对象,同时减少创建时的依赖。而创建设计模式就是解决此问题的一类设计模式。 单例模式【Singleton】 工厂模式【Factory】 抽象工厂模式【AbstractFactory】 建造者模式【Builder】 原型模式【Prototype】 结构设计模式(Structural Patterns)(7种):用于继承和接口时的设计模式。结构设计模式用于新类的函数方法设计,减少不必要的类定义,减少代码的冗余。 适配器模式【Adapter】 桥接模式【Bridge】 合成模式【Composite】 装饰器模式【Decorator】 门面模式【Facade】 代理模式【Proxy】 享元模式【Flyweight】 行为模式(Behavioral Patterns)(11种):用于方法实现以及对应算法的设计模式,同时也是最复杂的设计模式。行为设计模式不仅仅用于定义类的函数行为,同时也用于不同类之间的协议、通信。 策略模式【Strategy】 模板方法模式【TemplateMethod】 观察者模式【Observer】 迭代器模式【Iterator】 责任链模式【ResponsibilityChain】 命令模式【Command】 备忘录模式【Memento】 状态模式【State】 访问者模式【Visitor】 中介者模式【Mediator】 解释器模式【Interpreter】 按照范围分为:类的设计模式,以及对象设计模式 类的设计模式(Class patterns):用于类的具体实现的设计模式。包含了如何设计和定义类,以及父类和子类的设计模式。 对象设计模式(Object patterns): 用于对象的设计模式。与类的设计模式不同,对象设计模式主要用于运行期对象的状态改变、动态行为变更等。 设计模式原则 设计模式六大原则 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象. 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 迪米特法则:一个对象应该对其他对象保持最少的了解。 设计模式实现 1. Singleton(单例模式) 单例模式是最常见的模式之一,在Web应用的开发中,常常用于允许在运行时为某个特定的类创建仅有一个可访问的实例。 <?php final class Mysql { /** * * @var self[该属性用来保存实例] */ private static $instance; /** * * @var mixed */ public $mix; /** * Return self instance[创建一个用来实例化对象的方法] * * @return self */ public static function getInstance() { if (!...

2024年03月15日 · 16 min · Leanku

Redis持久化及过期删除策略

Redis持久化及过期删除策略 Redis 持久化之RDB和AOF RDB 详解 快照(snapshotting,RDB) RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据 从配置文件了解RDB 打开 redis.conf 文件,找到 SNAPSHOTTING 对应内容 RDB核心规则配置(重点) save <seconds> <changes> #save "" save 900 1 save 300 10 save 60 10000 说明:save <指定时间间隔> <执行指定次数更新操作>,满足条件就将内存中的数据同步到硬盘中。官方出厂配置默认是 900秒内有1个更改,300秒内有10个更改以及60秒内有10000个更改,则将内存中的数据快照写入磁盘。 若不想用RDB方案,可以把 save “” 的注释打开,下面三个注释。 指定本地数据库文件名,一般采用默认的 dump.rdb dbfilename dump.rdb 指定本地数据库存放目录,一般也用默认配置 dir ./ 默认开启数据压缩 rdbcompression yes 解说:配置存储至本地数据库时是否压缩数据,默认为yes。Redis采用LZF压缩方式,但占用了一点CPU的时间。若关闭该选项,但会导致数据库文件变的巨大。建议开启。 触发RDB快照 在指定的时间间隔内,执行指定次数的写操作 执行save(阻塞, 只管保存快照,其他的等待) 或者是bgsave (异步)命令 执行flushall 命令,清空数据库所有数据,意义不大。 执行shutdown 命令,保证服务器正常关闭且不丢失任何数据,意义…也不大。 注意: save备份过程:save备份是同步的,如果备份的数据量过大的话,服务器会暂停几百毫秒甚至是1秒 bgsave备份过程:bgsave备份会单独创建一个子进程,将备份的数据写入一个临时文件 RDB数据还原 找到备份临时文件的指令是 config get dir 指令执行成功以后将备份临时文件的目录拷贝到Redis的安装目录下 然后重新启动Redis服务就成功还原数据了...

2024年03月13日 · 1 min · Leanku

Redis中的Lua

Redis中的Lua 一. Redis中的Lua脚本的作用 Redis中的Lua脚本主要解决复杂操作的原子性和性能优化两大核心问题。它允许你在Redis服务器端直接执行自定义的逻辑,而不是把数据拉到客户端处理后再写回去。 核心作用 1. 保证原子性操作 Redis执行Lua脚本时,脚本中的所有命令会作为一个整体被执行,中间不会被其他命令插入。这完美解决了多命令组合操作时的并发安全问题。 经典场景: 实现分布式锁、库存扣减、限流计数器等。比如秒杀场景下,检查库存、扣减库存、记录订单这三个操作必须原子执行,用Lua脚本就能确保数据一致性。 2. 减少网络开销 将多个Redis命令合并到一个Lua脚本中,原本需要多次网络请求的操作变成一次请求完成。数据在Redis服务器本地处理,避免了大量数据在客户端和服务器之间来回传输。 3.扩展Redis指令集 你可以用Lua实现Redis原生不支持的复杂业务逻辑。比如自定义数据结构操作、复杂条件判断、循环处理等,让Redis变成一个具备计算能力的"小数据库"。 4. 提高代码复用率 脚本可以被缓存到Redis服务器,客户端通过SHA1摘要重复调用,无需每次都发送完整的脚本代码。多个应用可以共享同一套脚本逻辑 总结 Redis Lua脚本让你能把多个操作打包成一个原子性的、在服务器本地执行的任务,既保证了数据一致性,又提升了性能。特别适合秒杀、分布式锁、计数器、复杂条件更新等需要"读-改-写"原子操作的场景。 二、Lua安装 windows下载地址 :https://luabinaries.sourceforge.net/ 三 、 Lua在Redis中最常用、最经典的几个应用场景 1. 在Redis中操作Lua脚本的常用命令 命令 作用 一句话解释 EVAL 执行给定的Lua脚本 直接把脚本和参数传给Redis运行一次。 SCRIPT LOAD 将脚本缓存到Redis 把脚本存到Redis里,会返回一个SHA1值作为“脚本ID”。 EVALSHA 根据SHA1值执行缓存的脚本 拿着“脚本ID”去执行之前存好的脚本,省流量,效率更高。 SCRIPT EXISTS 检查脚本是否已缓存 看看某个“脚本ID”对应的脚本还在不在Redis里。 SCRIPT KILL 终止正在运行的脚本 如果脚本执行太久卡住了,可以用这个命令尝试杀掉它。 SCRIPT FLUSH 清空所有缓存的脚本 一键清除Redis里缓存的所有脚本,操作要小心\-1。 2. 五大经典应用场景 分布式锁 这是Lua脚本在Redis中最经典的应用。获取锁和释放锁的多个步骤必须是一个原子操作,否则会出现并发问题。 获取锁:使用 SET NX PX 命令,一步到位地尝试设置一个带过期时间的键,保证只有一个客户端能拿到锁-8。 释放锁:释放锁时,需要先检查当前持有锁的客户端是否就是自己(通过一个唯一值比如UUID判断),然后再删除锁。这两个动作必须通过Lua脚本一起执行,才能避免误删别人的锁-2-8。 -- 安全的释放锁脚本 -- KEYS[1]: 锁的名称 -- ARGV[1]: 客户端的唯一标识 if redis....

2024年03月12日 · 2 min · Leanku