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分布式锁的正确使用方式.如果有不正确的地方,欢迎大家 ...
随机推荐
- Mybatis总结一之SQL标签方法
---恢复内容开始--- 定义:mapper.xml映射文件中定义了操作数据库的sql,并且提供了各种标签方法实现动态拼接sql.每个sql是一个statement,映射文件是mybatis的核心. ...
- Natas7 Writeup(任意文件读取漏洞)
Natas7: 页面出现了两个选项,点击后跳转,观察url发现了page参数,猜测可能存在任意文件读取漏洞. 且源码给了提示,密码在/etc/natas_webpass/natas8 中. 将/etc ...
- LeetCode--179场周赛题解
水题: class Solution { public: string generateTheString(int n) { string s; string a="a",b=&q ...
- 环境篇:Docker
环境篇:Docker www.docker.com Docker 是什么? Docker 是一个开源的应用容器引擎,基于Go语言并遵从Apache协议的开源,让开发者可以打包他们的应用以及依赖包到一个 ...
- 8千字干货教程|java反射精讲
java反射机制精讲 目录 1. 反射机制的概念 2. 反射的基础Class类 3. 反射的用法 4. 反射的应用示例 作者简介:全栈学习笔记,一个正在努力的人 微信公众号:公众号日更,精彩美文每天推 ...
- 基于海龟编辑器python少儿编程
Python 少儿教程 为什么要学习编程 扫地机器人.物流机器人.自动泊车系统.无人超市.3D打印.微信.支付宝等等,随着人工智能时代的到来,越来越多的岗位将被机器人所替代. 所以,学习编程的最终目的 ...
- 怎样设计最优的卷积神经网络架构?| NAS原理剖析
虽然,深度学习在近几年发展迅速.但是,关于如何才能设计出最优的卷积神经网络架构这个问题仍在处于探索阶段. 其中一大部分原因是因为当前那些取得成功的神经网络的架构设计原理仍然是一个黑盒.虽然我们有着关于 ...
- ElasticSearch 9200 9300 端口
9300端口: ES节点之间通讯使用 9200端口: ES节点 和 外部 通讯使用 9300是TCP协议端口号,ES集群之间通讯端口号 9200端口号,暴露ES RESTful接口端口号
- Java系列之数组
原文首发于微信公众号:jzman-blog,欢迎关注交流! 本来打算温习一下注解方面的内容作为今天的推送,但是来不及写了,那就一起来看一下数组,数组是用来存放一组具有相同类型数据的数据结构,通过下标来 ...
- docker 搭建keepalived+nginx高可用
前言 最近工作 中 有用到keepalived,就想着 在 本地 搭建一套环境验证一下相关的功能.因为创建虚拟机比较麻烦,就借助 docker来搭建这样 一套 环境 ,顺带学习 巩固下docker的 ...