解锁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锁的正确姿势的更多相关文章

  1. 解锁 redis 锁的正确姿势

    redis 是 php 的好朋友,在 php 写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为.这个时候我们就要用到锁.锁的方式有好几种,php 不能在内存中用锁,不能使用 zo ...

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

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

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

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

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

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

  5. Spring Boot 2实现分布式锁——这才是实现分布式锁的正确姿势!

    参考资料 网址 Spring Boot 2实现分布式锁--这才是实现分布式锁的正确姿势! http://www.spring4all.com/article/6892

  6. Redis实现分布式锁的正确姿势

    分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介绍Re ...

  7. Redis分布式锁的正确姿势

    1. 核心代码: import redis.clients.jedis.Jedis; import java.util.Collections; /** * @Author: qijigui * @C ...

  8. 掌握Redis分布式锁的正确姿势

    本文中案例都会在上传到git上,请放心浏览 git地址:https://github.com/muxiaonong/Spring-Cloud/tree/master/order-lock 本文会使用到 ...

  9. Redis: 分布式锁的正确实现方式(转)

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

随机推荐

  1. [CSS3]学习笔记-CSS基本样式讲解

    1.CSS样式-背景 CSS运行应用纯色作背景,也允许使用背景图像创建相当复杂的效果 <!DOCTYPE html> <html> <head lang="en ...

  2. 第七届蓝桥杯javaB组真题解析-生日蜡烛(第二题)

    题目 /* 生日蜡烛 某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛. 现在算起来,他一共吹熄了236根蜡烛. 请问,他从多少岁开始过生日party的? 请填写他开始 ...

  3. BOM数据基础 - Mobox物料编码管理及实现

    1 企业现状 在企业日常经营过程中会产生大量的文档,如设计图纸.变更单.计算书.设计方案等,如果是制造企业还会产生大量的产品.组成产品的零部件等物料,这些数据在进入信息系统前都需要有一个唯一的标识,也 ...

  4. ArcGIS Pro 简明教程(1)Pro简介

    ArcGIS Pro 简明教程(1)Pro简介 ArcGIS Pro已经发布了相当的一段时间了,截至笔者写这系列文章的时候已经是1.3版本了,已经是相当完善的一个版本,基本上已经完成了原来ArcGIS ...

  5. 纯CSS3动画:一棵跳舞的树

    <!DOCTYPE html><head><meta http-equiv="Content-Type" content="text/htm ...

  6. PHP 数组处理

    一:PHP 定义数组: PHP 代码  不能再 空的位置 打字  会报错 定义数组  方式1 $cars=array("Volvo","BMW","T ...

  7. java一维数组学习

    /* * java学习: * 一维数组的使用: 声明语法 DataType[] name 或 DataType name[]. 初始化语法 DataType[] name = new DataType ...

  8. 初学HTML5

    Document 什么是HTML5? 首先了解html:html即超文本语言,这是一种语法简单.结构清晰的语 解析型文档,他不同于其他的编程语言. html5就是html网页标记语言的第五次重大更新产 ...

  9. 关于 <textarea ></textarea >标签在苹果微信浏览器出现 内阴影

    解决方法:(去除浏览器默认的样式元素) textarea  { box-shadow:0px 0px 0px rgba(0,0,0,0); -webkit-appearance:none; }

  10. Tree on the level UVa122

    很单纯的树的遍历,但是输入和方向好麻烦!!下面给出代码,题目来自UVa 122 #include<cstdio> #include<cstring> #include<v ...