栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Redis 分布式锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Redis 分布式锁

redis实现分布式锁

锁的目的是保证同一资源在同一个时间内只有一个线程访问该资源,实现ACID种的隔离性;
一般实现锁的方式有这么几种:

  • synchorinized 代码锁
  • 数据库行锁或者表锁(例如乐观锁)
  • redis分布式锁

前2种锁大部分情况下主要用在单体应用下,而redis分布式锁则主要用在分布式系统种。下面简单的列举一下redis分布式锁的实现流程:

在使用锁之前,我们得先考虑一些问题:

  • 互斥性
  • 防死锁
  • 锁的续期
  • 加所和解锁必须为同一个进程

带着这些问题,我们简单的介绍一下redis中如何解决:

  1. 加锁

要想获得锁,我们必须现获得一个锁,redis中获取一个分布式锁的伪代码:

// setnx 命令即为获取redis分布式锁,返回1,则为获取到了锁,反之为没有获取到锁
setnx(key,value)
  1. 释放锁
    获取到锁了以后,在执行同步代码以后,我们得释放锁,伪代码:
del(key)

锁无法释放的问题
那么这里有一个问题:线程A和线程B同时获取分布式锁,线程A先获取到,但是意外发生了,线程A挂掉了,这时候还没来得及进行del释放锁;那么线程B永远获取不到锁,

那么这里我们就要给线程A获取到的锁添加一个过期时间。伪代码:

//获取锁
> setnx(key,value)

//设置过期时间 :30s
> expire(key,30)

....执行同步代码块.....

> del(key)

也就是解决了上面一个问题,但是也引发了另外一个问题:由于setnx(key,value) 和expire(key,expiretime) 这是两个命令,无法保证原子性;这样一来,上叙问题又重现了,没有在根本上解决问题,而setnx又不支持同时设定过期时间,那么有没有一条命令就把两件事干完呢?答案:有 如下伪代码:

// set(key,value,expireTime,NX)
> set("mylock","11121233343dfasdfe12312",30,NX)

锁提前释放的问题

我们在set(key,value,expireTime,NX)时设置了过期时间,但是30s我们的代码还没处理完业务,这个lock就过期了,这个锁就释放了,而这个时候线程B又获取到了锁,当线程A处理完业务后,执行del,其实这个时候del的是线程B的锁,

这时候我们不妨在执行del时,先判断一下是否时线程A的锁。那么我们在set key时,可以把当前节点的ID或者线程ID 一同设置到key中,这样判断起来就有根据;

线程A线程B并发的问题

虽然我们通过 set value时 添加线程ID或者节点ID可以避免误删锁,但是这里又有一个问题,就是在同一时间内,线程A和线程B都访问了同一资源,这显然不符合隔离性;

我们可以通过给线程A添加一个守护线程,隔一段时间就去查一下线程A是否还持有锁,业务有没有处理完,没有,守护线程就给线程A的锁续命20s,线程A业务处理完以后,同步销毁守护线程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/306156.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号