redis 正确实现分布式锁的正确方式
前言
最近在自己所管理的项目中,发现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 正确实现分布式锁的正确方式的更多相关文章
- Redis系列四 - 分布式锁的实现方式
前言 分布式锁一般有3中实现方式: 数据库乐观锁: 基于Redis的分布式锁: 基于ZooKeeper的分布式锁. 以下将详细介绍如何正确地实现Redis分布式锁. 可靠性 首先,为了确保分布式锁的可 ...
- 一个Redis实现的分布式锁
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...
- Redis实现分布式锁的正确使用方式(java版本)
Redis实现分布式锁的正确使用方式(java版本) 本文使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景. 分布式锁一般有三种实现方式: 1. 数据库乐观锁: ...
- 基于Redis分布式锁的正确打开方式
分布式锁是在分布式环境下(多个JVM进程)控制多个客户端对某一资源的同步访问的一种实现,与之相对应的是线程锁,线程锁控制的是同一个JVM进程内多个线程之间的同步.分布式锁的一般实现方法是在应用服务器之 ...
- 【分布式缓存系列】集群环境下Redis分布式锁的正确姿势
一.前言 在上一篇文章中,已经介绍了基于Redis实现分布式锁的正确姿势,但是上篇文章存在一定的缺陷——它加锁只作用在一个Redis节点上,如果通过sentinel保证高可用,如果master节点由于 ...
- 【分布式缓存系列】Redis实现分布式锁的正确姿势
一.前言 在我们日常工作中,除了Spring和Mybatis外,用到最多无外乎分布式缓存框架——Redis.但是很多工作很多年的朋友对Redis还处于一个最基础的使用和认识.所以我就像把自己对分布式缓 ...
- Redis全方位详解--数据类型使用场景和redis分布式锁的正确姿势
一.Redis数据类型 1.string string是Redis的最基本数据类型,一个key对应一个value,每个value最大可存储512M.string一半用来存图片或者序列化的数据. 2.h ...
- 如何用redis正确实现分布式锁?
先把结论抛出来:redis无法正确实现分布式锁!即使是redis单节点也不行!redis的所谓分布式锁无法用在对锁要求严格的场景下,比如:同一个时间点只能有一个客户端获取锁. 首先来看下单节点下一般r ...
- 七种方案!探讨Redis分布式锁的正确使用姿势
前言 日常开发中,秒杀下单.抢红包等等业务场景,都需要用到分布式锁.而Redis非常适合作为分布式锁使用.本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式.如果有不正确的地方,欢迎大家 ...
随机推荐
- CentOS7设置环境变量
目录 一.环境变量的概念 1.环境变量的含义 2.环境变量的分类 3.Linux环境变量 二.常用的环境变量 1.查看环境变量 2.常用的环境变量 三.设置环境量 1.系统环境变量 2.用户环境变量 ...
- Vue 使用百度地图 实现搜索 定位
要求能定位到国外 及 查看了文档 百度支持东南亚大部分地区 满足需求 从而使用百度地图 <template> <div class="addHospital"& ...
- selenium3浏览器驱动设置
设置浏览器驱动: 1.首先手动创建一个存放浏览器驱动的目录,如: C:\driver , 将下载的浏览器驱动文件(例如:chromedriver.geckodriver)丢到该目录下. 2.打开计算机 ...
- 优秀DevOps工程师必会的33个面试题
DevOps面试问题 01 您能告诉我们DevOps和Agile(敏捷)之间的根本区别吗? 答:尽管DevOps与敏捷方法(这是最流行的SDLC[Software Development Life C ...
- Leetcode_474. 一和零(二维01背包)
每个字符串看成一个物品,两个属性是0和1的个数,转换为01背包. code class Solution { public: int w[605][2]; int dp[105][105]; int ...
- pycharm 2.7 快捷键
提示 CTRL Q: 在参数列表位置,显示可以输入的所有参数 CTRL Q: 查看选中方法的文档字符串 阅读 CTRL -: 折叠当前代码 CTRL +: 展开当前代码 CTRL SHIFT -: 折 ...
- iOS 页面流畅技巧(2)
一.屏幕显示图像的原理 首先从过去的 CRT 显示器原理说起.CRT 的电子枪按照上面方式,从上到下一行行扫描,扫描完成后显示器就呈现一帧画面,随后电子枪回到初始位置继续下一次扫描.为了把显示器的显示 ...
- [noip2016]愤怒的小鸟<状压dp+暴搜>
题目链接:https://vijos.org/p/2008 现在回过头去看去年的考试题,发现都不是太难,至少每道题都有头绪了... 这道题的数据范围是18,这么小,直接暴力呗,跑个暴搜就完了,时间也就 ...
- JS 剑指Offer(六) 用两个栈实现队列
题目:用两个栈实现队列,实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数,若队列中没有元素deleteHead返回-1 分析:在队列的尾部插入 ...
- ssh-add和ssh-agent
注: 因为在ssh-agent异常关闭或者新开窗口是会导致ssh-add找不到私钥,导致添加的私钥无效,所以下面使用keychain管理 ssh-add 参数 -l 查看代理中的私钥 -L 查看代理中 ...