redis分布式锁(转)
add by zhj: 如果不考虑键的删除,而是让他过期后自动失效,那用set就可以实现锁了
原文:http://www.cnblogs.com/yjf512/archive/2017/03/22/6597814.html
解锁redis锁的正确姿势
redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为。这个时候我们就要用到锁。锁的方式有好几种,php不能在内存中用锁,不能使用zookeeper加锁,使用数据库做锁又消耗比较大,这个时候我们一般会选用redis做锁机制。
setnx
锁在redis中最简单的数据结构就是string。最早的时候,上锁的操作一般使用setnx,这个命令是当:lock不存在的时候set一个val,或许你还会记得使用expire来增加锁的过期,解锁操作就是使用del命令,伪代码如下:
if (Redis::setnx("my:lock", 1)) {
Redis::expire("my:lock", 10);
// ... do something
Redis::del("my:lock")
}
这里其实是有问题的,问题就在于setnx和expire中间如果遇到crash等行为,可能这个lock就不会被释放了。于是进一步的优化方案可能是在lock中存储timestamp。判断timestamp的长短。
set
现在官方建议直接使用set来实现锁。我们可以使用set命令来替代setnx,就是下面这个样子
if (Redis::set("my:lock", 1, "nx", "ex", 10)) {
... do something
Redis::del("my:lock")
}
上面的代码把my:lock设置为1,当且仅当这个lock不存在的时候,设置完成之后设置过期时间为10。
获取锁的机制是对了,但是删除锁的机制直接使用del是不对的。因为有可能导致误删别人的锁的情况。
比如,这个锁我上了10s,但是我处理的时间比10s更长,到了10s,这个锁自动过期了,被别人取走了,并且对它重新上锁了。那么这个时候,我再调用Redis::del就是删除别人建立的锁了。
官方对解锁的命令也有建议,建议使用lua脚本,先进行get,再进行del
程序变成:
$token = rand(1, 100000);
function lock() {
return Redis::set("my:lock", $token, "nx", "ex", 10);
}
function unlock() {
$script = `
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
`
return Redis::eval($script, "my:lock", $token)
}
if (lock()) {
// do something
unlock();
}
这里的token是一个随机数,当lock的时候,往redis的my:lock中存的是这个token,unlock的时候,先get一下lock中的token,如果和我要删除的token是一致的,说明这个锁是之前我set的,否则的话,说明这个锁已经过期,是别人set的,我就不应该对它进行任何操作。
所以:不要再使用setnx,直接使用set进行锁实现。
redis分布式锁(转)的更多相关文章
- 利用redis分布式锁的功能来实现定时器的分布式
文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...
- Redis分布式锁
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- spring boot redis分布式锁
随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...
- Redis分布式锁的正确实现方式
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- Redis分布式锁---完美实现
这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...
- redis分布式锁实践
分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...
- Redis分布式锁的try-with-resources实现
Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...
- 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
随机推荐
- 批量 kill mysql 线程
时常有一些烂sql跑在数据库里,我们要进行kill,避免影响拖垮数据库. mysql> show processlist; +----+------+---------------------+ ...
- Docker入门学习总结
1. 什么是Docker Docker是一种虚拟化技术,其在容器的基础上进一步封装了文件系统.网络互联.进程隔离等等,从而极大地简化了容器的创建和维护.Docker使用 Google 公司推出的 Go ...
- Y460 安装ubuntu 12.04系统黑屏,登录界面黑屏
ubuntu 12.04系统黑屏,登录界面黑屏,但是命令行界面可以登录,也可以正常使用,当时在装CVS,装完重启就这样了,可能是因为前一天装更新时,突然断电导致图形界面损坏,参考他人方法,终于修复,总 ...
- maven命令package、install、deploy比较
maven生命周期(lifecycle)由各个阶段组成,每个阶段由maven的插件plugin来执行完成.生命周期(lifecycle)主要包括clean.resources.complie.inst ...
- [IR] Advanced XML Compression - XBW
思考:与ISX对比后能得出什么结论 原理解析: We proposed the XBW-transform that mimics on trees the nice structural prope ...
- asp.net mvc 3.0 知识点整理 ----- (3).HtmlHelper(Html 辅助方法)介绍
在View视图中,Html的类型是System.Web.Mvc.HtmlHelper<T>, 所有的辅助方法都需要和ModelState交互.那么,ModelState是什么呢?它是模型绑 ...
- Apache Nginx URL 地址 重写
URL重写这东西在工作中用了很多次了,但每次都忘记了要记得把知道的积累下来. 哎,要么认为没必要,要么就是没时间?! 一.Apache 篇 官方地址:http://man.chinaunix.net/ ...
- JdbcTemplate in()传参
1. 实体类 import java.util.List; public class Param { private List<String> names; private List< ...
- docker学习网站
https://yeasy.gitbooks.io/docker_practice/content/compose/install.html docker compose scal 的应用举例 htt ...
- pythonCharm 破解
操作步骤和IDEA是一样的 只是jar 包不一样 //激活拷贝-javaagent:E:\PythonCharm\PyCharm Community Edition 2017.3.4\bin\Jetb ...