文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。

在实际项目开发中经常会遇到这样一个业务场景:如果同一台机器有多个线程抢夺同一个共享资源,同一个线程多次执行会出现异常,这种情况下就会出现非线程安全。我们解决方法通常使用锁来解决。但是如果有多台机器呢?这时候我们通常使用分布式锁来解决分布式环境下共享资源的同步问题。实现分布式锁常见有Redis,zookeeper等,今天主要就是讲讲如何使用Redis实现分布式锁。

使用Redis实现分布式锁的方案其实很简单,首先我们先实现一个方案一:每次执行请求的时候,机器先查询Redis中是否存在分布式锁的key,如果不存在锁的key,就以该锁为key,value取随机数写入到Redis中,然后开始执行请求。

方案一看起来很简单,但是这样的处理逻辑不可避免的存在两个致命的BUG:第一:如果一个进程成功取到锁,但是这时候这个机器出现故障宕机了,分布式的锁没有得到释放,就造成了死锁的产生了。第二:如果同一时间存在两个机器同时查询Redis,都发现Redis不存在锁的key,于是都成功获得了锁。

这时候我们可以这么处理改善方案一实现方案二:Redis有提供一个原子写入操作的命令:setnx,setnx只有在锁的key不存在的情况下才允许设置key值,所以说问题2同一个锁在同一时间可能会被不同机器获取到的问题就可以得到解决,而且setnx命令可以设置key值的超时时间,所以在写入锁的key时可以为锁设置一个超时时间,如果超过超时时间锁还未释放就会释放,则其他机器在key释放后也可以继续写入key占有锁执行对应的请求。这样问题1机器宕机造成锁无法及时释放的问题也因此迎刃而解。

但是这又造成了另外一个潜在的问题:如果某个机器执行耗时操作,超时时间过去了请求还未执行完,锁就会被释放掉被新的机器占有,等耗时任务结束时执行释放锁的操作,这时候释放的锁不是自己的锁而是已经被其他机器占有的锁。

这时候我们可以将方案再做适当的修改变成方案三:当某个机器占有锁并在Redis中设置key时,将value设置为随机数,在请求处理完毕需要释放锁之前加上一步操作:判断key的value值是否等于之前设置的随机数,如果是代表这个锁占有者还是自己,就可以执行释放锁操作,否则代表锁已经被别人占有,不能执行释放锁操作,这样就可以解决可能误操作释放他人锁的问题。但是由于查询和释放锁的操作非原子性的,所以可能出现一种情况:在查询key时发现key的value和机器本身设置的一直,但是还没来得急释放锁时,锁过期被释放了,这时候执行释放锁操作就会导致释放的依旧是其他机器占有的锁,所以我们方案三需要进一步的改进,也就是我们必须要保证查询锁和释放锁这两步操作必须是原子性的,这时候我们就需要使用另一种方式:引入Jedis,使用Lua脚本将查询锁和释放锁的两部分逻辑写成脚本,于是Redis执行Lua脚本时,其他机器的所有命令都必须等到Lua脚本执行结束才能执行,所以不可能存在查询锁结束还未释放就被其他机器占领的情况。

到这里我们介绍完了如何使用Redis实现分布式锁,但是这是基于单机部署,如果Redis是使用多机部署,每个主节点还有有子节点,由于Redis主从复制是异步操作,所在上述方案肯定会出现问题的,多机部署可以采用Redission实现分布式锁,这是官方提供的组件,如果感兴趣可以自己阅读下文档:
https://github.com/redisson/redisson

欢迎关注公众号:程序猿周先森

Redis优雅实现分布式锁的更多相关文章

  1. 基于redis实现的分布式锁

    基于redis实现的分布式锁 我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源.锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标 ...

  2. 一个Redis实现的分布式锁

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...

  3. 基于Redis的简单分布式锁的原理

    参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...

  4. redis客户端、分布式锁及数据一致性

    Redis Java客户端有很多的开源产品比如Redission.Jedis.lettuce等. Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持:Redis ...

  5. Redis系列(二)--分布式锁、分布式ID简单实现及思路

    分布式锁: Redis可以实现分布式锁,只是讨论Redis的实现思路,而真的实现分布式锁,Zookeeper更加可靠 为什么使用分布式锁: 单机环境下只存在多线程,通过同步操作就可以实现对并发环境的安 ...

  6. 在redis上实现分布式锁

    /** *在redis上实现分布式锁 */ class RedisLock { private $redisString; private $lockedNames = []; public func ...

  7. 如何用redis正确实现分布式锁?

    先把结论抛出来:redis无法正确实现分布式锁!即使是redis单节点也不行!redis的所谓分布式锁无法用在对锁要求严格的场景下,比如:同一个时间点只能有一个客户端获取锁. 首先来看下单节点下一般r ...

  8. redis系列:分布式锁

    redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  9. 一般实现分布式锁都有哪些方式?使用redis如何设计分布式锁?使用zk来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?

    #(1)redis分布式锁 官方叫做RedLock算法,是redis官方支持的分布式锁算法. 这个分布式锁有3个重要的考量点,互斥(只能有一个客户端获取锁),不能死锁,容错(大部分redis节点创建了 ...

随机推荐

  1. [python]代码中包含中文,提示:SyntaxError: Non-ASCII character '\xcd'

    解决方法: 把文件编码方式改为gbk即可.在代码开头写上: # coding=gbk

  2. HDU4289Control 无向图拆点最大流

    /* ** 无向图拆点,求最大流,最大流即为割点个数. */ #include <iostream> #include <cstdio> #include <cstrin ...

  3. Charles安装windows篇

    简介 Charles是一款非常好用的网络抓包工具,类似fiddle抓包工具,当然也可以理解为一款HTTP代理服务器.HTTP监视器.反向代理服务器等. 二.官网下载 地址:https://www.ch ...

  4. Mysql 用户root密码重置

    Asterisk安装完成之后,接手新的Asterisk系统后不清楚Mysql的root账号密码. 重新重置mysql的root密码的方式 先查看mysql的版本号. 我的测试环境下的mysql版本为5 ...

  5. 2019本科se第一次作业-博客初体验-chris

    (1)第一章  计算机专业术语总结: 软件=程序+软件工程.程序=数据结构+算法.软件.程序.用户.需求.应用程序.软件服务.源程序.软件架构(Software Architecture).软件设计与 ...

  6. python列表排序用法

    错误用法::: a=list('hdfoiegfjil').sort()

  7. Net基础篇_学习笔记_第十一天_面向对象(面向过程与面向对象的区别/类的概念)

    1.面向过程-----> 面向对象 面向过程:面向的是完成这件事儿的过程,强调的是完成这件事儿的动作. 把大象塞进冰箱里1.打开冰箱门2.把大象塞进去,亲下大象的屁股3.关闭冰箱门 孙全 瘦小 ...

  8. 喜大普奔,两个开源的 Spring Boot + Vue 前后端分离项目可以在线体验了

    折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...

  9. 装系统---------- u盘 安装系统

    1.首先根据你的电脑品牌进入bios 模式 如何进入:  不同电脑品牌进入bios 方法 进入之后设置启动方式 将第一启动设置为U盘启动设置好后 使用 Fn + F10  保存 2.使用制作好的 U盘 ...

  10. [Advanced Python] 13 - "Decorator": syntactic sugar

    单独一章复习:Python 函数装饰器,廖雪峰讲装饰器 基本概念 函数作为变量 从函数中返回函数 子函数写在外面貌似也可以,可这样就少了“封装性”. def greet(): return " ...