setNX,是set if not exists 的缩写,也就是只有不存在的时候才设置, 设置成功时返回 1 , 设置失败时返回 0 。可以利用它来实现锁的效果,但是很多人在使用的过程中都有一些问题没有考虑到。

例如某个查询数据库的接口因为请求量比较大所以加了缓存,并设定缓存过期后刷新。当并发量比较大并且缓存过期的瞬间,大量并发请求会直接查询数据库导致雪崩。如果使用锁机制来控制只有一个请求去更新缓存就能避免雪崩的问题。下面是很多人下意识想到的加锁方法

$rs = $redis->setNX($key, $value);

if ($rs) {

//处理更新缓存逻辑

// ......

//删除锁

$redis->del($key);

}

?>

通过 setNX 获取锁,如果成功了则更新缓存然后删除锁。其实这里有一个严重的问题:如果更新缓存的时候因为某些原因意外退出了,那么这个锁就不会被删除而一直存在,以至于缓存再也得不到更新。为了解决这个问题有人可能会想到给锁设置一个过期时间,如下

$redis->multi();

$redis->setNX($key, $value);

$redis->expire($key, $ttl);

$redis->exec();

?>

因为 setNX 不具备设置过期时间的功能,所以要借助 Expire 来设置,同时需要使用 Multi/Exec 来确保请求的原子性,以免 setNX 成功了 Expire 却失败了。这样还有问题:当多个请求到达时,虽然只有一个请求的 setNX 可以成功,但是任何一个请求的 Expire 却都可以成功,这就意味着即便获取不到锁也可以刷新过期时间,导致锁一直有效,还是解决不了上面的问题。显然 setNX 满足不了需求,Redis从 2.6.12 起,SET 涵盖了 SETEX 的功能, SET 本身又包含了设置过期时间的功能,所以使用 SET 就可以解决上面遇到的问题。

$rs = $redis->set($key, $value, array('nx', 'ex' => $ttl));

if ($rs) {

//处理更新缓存逻辑

// ......

//删除锁

$redis->del($key);

}

?>

到这一步其实还是有问题的,如果一个请求更新缓存的时间比锁的有效期还要长,导致在缓存更新过程中锁就失效了,此时另一个请求就会获取到锁,但前一个请求在缓存更新完毕的时候,直接删除锁的话就会出现误删其它请求创建的锁的情况。所以要避免这种问题,可以在创建锁的时候需要引入一个随机值并在删除锁的时候加以判断

$rs = $redis->set($key, $random, array('nx', 'ex' => $ttl));

if ($rs) {

//处理更新缓存逻辑

// ......

//先判断随机数,是同一个则删除锁

if ($redis->get($key) == $random) {

$redis->del($key);

}

}

?>

nx set 怎么实现的原子性_正确地使用Redis的SETNX实现锁机制相关推荐

  1. 正确使用Redis的setnx实现锁机制

    setnx,是set if not exists的缩写,也就是只有不存在的时候才设置,设置成功时返回1,设置失败时返回0.可以利用它来实现锁的效果,但是很多人在使用的过程中都有一些问题没有考虑到. 例 ...

  2. nx set 怎么实现的原子性_基于Redis的分布式锁实现

    前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...

  3. nx set 怎么实现的原子性_【redis进阶(1)】redis的Lua脚本控制(原子性)

    [toc] 为什么要用lua 减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成.使用脚本,减少了网络往返时延. 原子操作:Redis会将整个脚本作 ...

  4. java如何保证redis设置过期时间的原子性_分布式锁用 Redis 还是 Zookeeper

    在讨论这个问题之前,我们先来看一个业务场景: 系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户下单. 由于系统有 ...

  5. redis setnx原子性_不支持原子性的 Redis 事务也叫事务吗?

    文章收录在 GitHub JavaKeeper ,N线互联网开发必备技能兵器谱 假设现在有这样一个业务,用户获取的某些数据来自第三方接口信息,为避免频繁请求第三方接口,我们往往会加一层缓存,缓存肯定要 ...

  6. 分布式锁 哨兵模式_正确解锁分布式锁的各种姿势

    分布式锁 为什么要用分布式锁? 在分布式场景下多个客户端同时获取一把锁,为了保证只有一个客户端能获取到这把锁,分布式锁诞生了,而分布式锁的诞生就是为了解决数据的最终一致性.在分布式系统中有一个著名的原 ...

  7. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁

    1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...

  8. getset原子性 redis_一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)

    各个版本的Redis分布式锁 V1.0 V1.1 基于[GETSET] V2.0 基于[SETNX] V3.0 V3.1 分布式Redis锁:Redlock 总结 <Netty 实现原理与源码解 ...

  9. 一个项目部署多个节点会导致锁失效么_一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)...

    各个版本的Redis分布式锁 V1.0 V1.1 基于[GETSET] V2.0 基于[SETNX] V3.0 V3.1 分布式Redis锁:Redlock 总结 <Netty 实现原理与源码解 ...

最新文章

  1. ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider
  2. Velocity魔法堂系列二:VTL语法详解
  3. 怎么修改CAD编辑器中默认的线型
  4. 单元格格式_你最想要的自定义单元格格式来了!
  5. python的float精度_python 中的各种小数点后的精度处理方式
  6. Matlab中的文件读取函数
  7. 例用C# 变更文件夹时间
  8. RedisView-开源跨平台的Redis可视化工具
  9. python 压缩文件
  10. qq手机电脑消息同步_这届用户换机首选必备工具,QQ同步助手一键迁移手机资料...
  11. java移位运算符实验程序:lt;lt;(左移)、gt;gt;(带符 号右移)和gt;gt;gt;(无符号右移)...
  12. UVA10917 Walk Through the Forest
  13. CSS布局:让页脚始终保持底部的方法
  14. CAN FD解释-简单介绍
  15. codeforces #630 F. Selection of Personnel
  16. Python:练习打字游戏
  17. 程序员也要学英语——英语构词法
  18. Mysql 脚本创建触发器报错 1064 42000
  19. 深度分享:解读中国老年行业创新创业生态,六位创业者带来老年创投/社交电商/教育/旅游/化妆品一线实战经验心得!
  20. 怎样提高学生计算机应用能力,如何提高中职学生计算机应用能力

热门文章

  1. 请领导审阅并提意见应怎么说_职场中,领导不喜欢你,暗中排挤你,怎么办?老员工给你支5招!...
  2. P3373 【模板】线段树 2(区间乘法+区间加法+区间求和)
  3. 我的世界java版游戏崩溃_我的世界:MC不一样的冷知识,游戏崩溃?没想到你是这样的F3!...
  4. fscanf简单使用
  5. 为什么博图中放置按下按钮无反应_为什么点击按钮没反应呢?
  6. mac系统jmeter生成html报告,jmeter5.1.1 生成html报告
  7. linux c ftp断点续传,求个支持断点续传的ftp脚本
  8. leetcode刷题 74.搜索二维矩阵
  9. 网桥(bridge) 和 交换机(switch) 之异同
  10. 致技术创业的朋友:其实销售很简单(Z)