前言

最近在自己所管理的项目中,发现redis加锁的方式不对,在高并发的情况有问题。故在网上找搜索了一把相关资料。发现好多都是互相抄袭的,很多都是有缺陷的。好多还在用redis 的 setnx命令来实现分布式锁。其实redis 中的set命令本身就已经集成了setnx命令的功能了,而且比其还强大。这里,我使用 redis-cli 客户端 结合lua脚本 原生 的实现redis 分布式锁。

准备材料

  • redis-server
  • redis-cli

LUA 与 REDIS 的关系

从 redis2.6.0 开始, redis 内部就内置了lua解释器。lua也就是成了redis扩展的一种解决方案了。

格式:

eval scripts num [keys ...] [argv ...]
  • eval : redis中执行lua脚本的命令
  • scripts : lua脚本,不必一定得是lua函数
  • num : keys 的个数,用于区分 keys 和 argv ;没有keys,则写0
  • keys: 可变数组,一般用于表示redis 的键,下标从1 开始
  • argv: 可变数组,一般用于表示redis 的值,下标从1 开始

redis 与 lua 的交互

分两种情况:

  • redis 执行 lua 脚本 : 使用 redis中的 eval命令 即可
  • lua & redis
    • lua 接收 redis 发送过来的数据 , 在 SCRIPTS中使用 KEYS[] 与 ARGV[]
    • lua 调用redis 命令, 在SCRIPTS中使用 call() 或者 pcall()
    • lua 将结果返回给redis , 使用return

案例解析

1.利用lua 打印参数
127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],ARGV[2]}" 3 key1 key2 first second threed
1) "key1"
2) "second"
3) "threed"

2.通过lua 设置变量
# 设置一个 foo='hello' 键值对
127.0.0.1:6379> eval "return redis.call('set','foo','hello')" 0
OK
127.0.0.1:6379> scan 0
1) "0"
2) 1) "foo"
127.0.0.1:6379> get foo
"hello"
127.0.0.1:6379>
3.通过lua 传参的方式 设置变量
127.0.0.1:6379> eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name Bob
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"Bob"
127.0.0.1:6379>
4. 利用redis-cli 设置分布式锁
# 加锁 , 直接使用 set nx模式 【生产环境中123456 是一个唯一的随机数】
127.0.0.1:6379> set lock 123456 EX 40 NX
OK # 解锁 , 结合 lua脚本
127.0.0.1:6379> eval "if redis.call('get','lock') == ARGV[1] then return redis.call('del','lock') else return 0 end" 0 123456
(integer) 1 127.0.0.1:6379> get lock
(nil)

上面的lua脚本格式化后的样子如下:

if redis.call('get','lock') == ARGV[1]
then
return redis.call('del','lock')
else
return 0
end

redis 正确实现分布式锁的正确方式的更多相关文章

  1. Redis系列四 - 分布式锁的实现方式

    前言 分布式锁一般有3中实现方式: 数据库乐观锁: 基于Redis的分布式锁: 基于ZooKeeper的分布式锁. 以下将详细介绍如何正确地实现Redis分布式锁. 可靠性 首先,为了确保分布式锁的可 ...

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

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

  3. Redis实现分布式锁的正确使用方式(java版本)

    Redis实现分布式锁的正确使用方式(java版本) 本文使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景. 分布式锁一般有三种实现方式: 1. 数据库乐观锁: ...

  4. 基于Redis分布式锁的正确打开方式

    分布式锁是在分布式环境下(多个JVM进程)控制多个客户端对某一资源的同步访问的一种实现,与之相对应的是线程锁,线程锁控制的是同一个JVM进程内多个线程之间的同步.分布式锁的一般实现方法是在应用服务器之 ...

  5. 【分布式缓存系列】集群环境下Redis分布式锁的正确姿势

    一.前言 在上一篇文章中,已经介绍了基于Redis实现分布式锁的正确姿势,但是上篇文章存在一定的缺陷——它加锁只作用在一个Redis节点上,如果通过sentinel保证高可用,如果master节点由于 ...

  6. 【分布式缓存系列】Redis实现分布式锁的正确姿势

    一.前言 在我们日常工作中,除了Spring和Mybatis外,用到最多无外乎分布式缓存框架——Redis.但是很多工作很多年的朋友对Redis还处于一个最基础的使用和认识.所以我就像把自己对分布式缓 ...

  7. Redis全方位详解--数据类型使用场景和redis分布式锁的正确姿势

    一.Redis数据类型 1.string string是Redis的最基本数据类型,一个key对应一个value,每个value最大可存储512M.string一半用来存图片或者序列化的数据. 2.h ...

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

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

  9. 七种方案!探讨Redis分布式锁的正确使用姿势

    前言 日常开发中,秒杀下单.抢红包等等业务场景,都需要用到分布式锁.而Redis非常适合作为分布式锁使用.本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式.如果有不正确的地方,欢迎大家 ...

随机推荐

  1. css定位属性的运用

    position 定位定位:主要解决叠加排列的问题.position 1.static(默认) 2.relative : 相对定位 如果没有定位偏移量,对元素本身没有任何影响(一般用于需要加定位的父容 ...

  2. Linux---使用kill杀不掉进程解决方案

    今天打开Linux虚拟机,然后使用jps命令查看,莫名奇妙多了一个1889进程 然后使用kill杀掉后,再运行jps还是存在此进程.于是乎开始大量百度,最终找到了解决方案. 说的很清楚了,杀不掉的原因 ...

  3. flex弹性盒子实现微博页面

    结果图: 源代码: html部分: <!DOCTYPE html><html lang="en"><head> <meta charset ...

  4. go micro实战01:快速搭建服务

    背景 go-micro给我们提供了一个非常便捷的方式来快速搭建微服务,而且并不需要提前系统了解micro,下面用一个简单的示例来快速实现一个服务. 创建Proto文件 因为我们要做微服务,那么就一定有 ...

  5. 树莓派3B+安装&卸载mysql

    需求 在树莓派上 安装Mysql 服务,并开启远程访问 步骤 安装 mysql server 1 $ sudo apt-get install mysql-server 我以为中间会让我提示输入 数据 ...

  6. servlet本质是什么

    作者:Javdroider Hong链接:https://www.zhihu.com/question/21416727/answer/339012081来源:知乎著作权归作者所有.商业转载请联系作者 ...

  7. DRF之APIView源码简析

    一. 安装djangorestframework 安装的方式有以下三种,注意,模块就叫djangorestframework. 方式一:pip3 install djangorestframework ...

  8. 非常详细的 Linux C/C++ 学习路线总结!已拿腾讯offer

    创作不易,点赞关注支持一下吧,我的更多原创技术分享,关注公众号「后端技术学堂」第一时间看! 最近在知乎经常被邀请回答类似如何学习C++和C++后台开发应该具体储备哪些基础技能的问题. 本身我从事的的C ...

  9. JUC 中提供的限流利器-Semaphore(信号量)

    在 JUC 包下,有一个 Semaphore 类,翻译成信号量,Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源.Semaphore 跟锁 ...

  10. C#中的9个“黑魔法”与“骚操作”

    C#中的9个"黑魔法"与"骚操作" 我们知道C#是非常先进的语言,因为是它很有远见的"语法糖".这些"语法糖"有时过于好 ...