Redis经典应用-分布式锁

前言

在多线程的学习中,提到过为了保证多线程运行时的线程安全,需要通过锁来做互斥控制

在分布式系统中,也会涉及多个节点访问同一个公共资源的问题,由于之前学的锁都是只能在当前进程内生效,在分布式系统多个进程多个主机的场景就无能为力了

因此,要引入分布式锁来解决这个问题

一.分布式锁

所谓分布式锁,也是一个/一组单独的服务器程序,为其他服务器提供"加锁"这样的服务,redis就是一种典型的可以实现分布式锁的方案

在redis中,所谓加锁就是给redis设置一个key-value,如果这个键值对不存在,则设置,成功加锁

如果已经存在,说明已经有进程进行了加锁,则阻塞等待或者销毁(看具体的策略)

而解锁,则是将键值对进行删除

在redis的学习中,set nx正好很符合加锁的步骤,无则添加,有则失败

如果服务器进程挂了,那加锁的程序则会无法解锁

对此,我们可以为锁设置过期时间,这样即使服务器挂了,锁到设定时间也会自动解除

因此,加锁命令应为 set ex nx

二.常见问题

如果一个一台服务器加锁,此时另一台服务器执行了解锁,那锁岂不白加了??

对此,为了不让其他服务器误解锁,需要对解锁操作增加一个校验机制

首先,给服务器编号,每一个服务器都有一个自己的身份标识

进行加锁时,key对应的是对哪个资源进行加锁,value则是服务器的编号

在后续解锁时,就可以先Get服务器的编号,并进行判断是否与加锁的服务器编号一致.

如果在解锁时,有两个线程在进行解锁操作,会不会造成什么影响??

表面上看,会执行两次get与del操作,当一个线程结束del后,另一个线程再执行一次,也不会有什么影响

实际上,这是及其线程不安全的情况,当有一个线程结束del操作后,第二个在del之前,万一有其他线程在此中间进行了加锁操作,这个锁则会被第二个线程del操作解锁,造成业务运行逻辑出错.

该问题的产生是由于解锁操作不是原子的,对此,我们将操作变成原子的即可

虽然redis事务可以解决问题,但redis官方已经给出了更好的解决方法:lua脚本

redis在官方文档也明确表示,lua脚本是事务的替代方案

过期时间续约问题

锁的过期时间短,可能业务逻辑还没执行完成,锁就释放了

如果设置时间长,也会导致锁"释放时间过长"的问题

对于如果设置过期时间,"动态续约"是更好的方法

在初始情况下,设置一个较短的过期时间,当剩余时间低于设定值的时候,而任务还没执行完,则自动为锁续上时间.

如果运行过程中服务器崩了,自然也就不会进行续约,锁也会在短时间内被释放掉.

往往会有一个线程专门负责监测与续约,这个线程则被称为"看门狗"

redlock算法

使用redis作为分布式锁,那redis挂了咋整??

冗余!!

可以引入更多的redis节点,按照一定顺序对redis组进行加锁操作

如果某个节点挂了,也没有关系,继续给下一个redis节点加锁

当写入key的节点超过半数,则视为加锁成功

同理,进行解锁时也会经历上述步骤

相关推荐
Blossom i8 小时前
大数据预处理与采集实验一:使用Python操作MySQL数据库
数据库·mysql
雾时之林9 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
老纪的技术唠嗑局10 小时前
超级干货分享:中小企业使用 OceanBase 实践经验汇总
数据库
CLOUD ACE11 小时前
谷歌云代理|零售商Target 如何利用 Spanner Graph 提升零售发现体验并将数据库维护成本降低 50%
数据库·零售
AI大模型-小雄11 小时前
Codex写分页接口为什么越翻越慢?用Cursor Pagination解决重复与漏数据
大数据·数据库·elasticsearch·搜索引擎·chatgpt·后端开发·codex
少晓年11 小时前
从 MySQL 迁移到人大金仓 KingbaseES:完整指南与实践
数据库·mysql
SelectDB12 小时前
Apache Doris AI RAG 实战:从基础 RAG 到知识图谱增强的技术能力与选型
数据库
SelectDB12 小时前
电商企业 PostgreSQL 迁移 Apache Doris:80TB 分析数据统一平台技术能力与实践
数据库
SelectDB12 小时前
阶跃星辰 Agent 可观测:Apache Doris / SelectDB 的技术能力与实践
数据库
SelectDB12 小时前
ApacheDoris Iceberg V3 湖仓 DML:Apache Doris / SelectDB 的技术能力与实践
数据库