首页 > 数据库 >redis通过lua脚本------实现原子性操作(PHP代码实现)

redis通过lua脚本------实现原子性操作(PHP代码实现)

时间:2022-11-23 21:45:07浏览次数:35  
标签:脚本 127.0 0.1 redis lua num ------

背景

一直都知道redis里可以执行lua脚本,但是以前一直搞不懂redis为啥要这么搞,今天看了人家一篇博文,说秒杀场景出现商品超卖,解决方案是利用lua脚本来保证操作的原子性

自己也小试了一把程序,确实通过lua能保证操作的原子性,直接上代码。

 

【eval — lua脚本】 EVAL script numkeys key [key ...] arg [arg ...]
  • script: 你的lua脚本
  • numkeys: key的个数
  • key: redis中各种数据结构的替代符号
  • arg: 你的自定义参数
  示例:
127.0.0.1:6379> eval "return redis.call('mset',KEYS[1],ARGV[1],KEYS[2],ARGV[2])" 2 name age zhangsan 18
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> get age
“18"
 
127.0.0.1:6379> eval "return redis.call('hset',KEYS[1],ARGV[1],ARGV[2])" 1 foo abc 123
(integer) 1
127.0.0.1:6379> hgetall foo
1) "abc"
2) "123"

  

   

准备:

    将num键的值设置为1

测试,10个请求10个并发

   ab.exe -c10 -n10 http://www.test.com/redis.php

结果:

    不使用lua脚本的,num值会出现负数

    使用lua脚本的,num的值永远都是减至为0

结论

   redis执行时,其它客户端都会被暂停,永远只有一个lua脚本运行

代码如下:

<?php

$redis = new Redis(); 
$result=$redis->connect('127.0.0.1'); 


//不使用lua脚本,在并发访问情况下出现num的值为负数
if($redis->get('num')>0){
    //业务逻辑 todo
    $redis->decr('num');
}


//通过lua脚本,并发访问的情况下不会出现负数
$script=
<<<EOF
  if(tonumber(redis.call('get',KEYS[1]))>0) then
    redis.call('decr',KEYS[2])
    return 'ok'
  else
      return 'fail';
  end
EOF;
$hashresult = $redis->eval($script,['num','num'],2);//通过keys[n]能够访问到的变量个数
var_dump($hashresult); 

 

 

https://www.cnblogs.com/rcjtom/articles/8954398.html

标签:脚本,127.0,0.1,redis,lua,num,------
From: https://www.cnblogs.com/rxbook/p/16920218.html

相关文章

  • 恢复 IIS Express SSL证书 ,IIS Express 调试站点 ERR_CONNECTION_RESET
    前言:一波未平,另一波又起...之前写了篇“Asp.NetCore作为服务(WindowsService)部署与SSL设置整理”随笔,在操作过程中把IISExpress的证书给删掉了,然后其他程序......
  • 决策单调性优化dp二则
    CielandGondolas  CodeForces-321E题意:有n个人,第i个人和第j个人放在一起时会产生a[i][j]的沮丧值(是社恐吗),保证a[i][j]=a[j][i],两个人只产生一份沮丧值。将n个人分成......
  • 衣服搭配技巧
    衬衫     比较合身的尺寸是       优衣库:XL180-108B  注意不要在优衣库买纯棉的衣服,不是很抗皱,穿上半天就特别特别皱了衬衫选购技巧:衣领:扣......
  • Testbench 的编写与应用
    1.Testbench的概念Testbench是一种用任意语言编写的程序或模块,用于在模拟过程中执行和验证硬件模型的功能正确性。Verilog主要用于硬件建模(模拟),该语言包含各种资源,用于......
  • vue中根据不同的开发环境配置不同的请求地址
    4、Vue环境变量配置在开发的时候一般会有是三个环境:开发环境测试环境线上环境vue中有个概念就是模式,默认先vuecli有三个模式development开发环境模式用于vue......
  • easylogging++的那些事(二)宏定义
    上一篇文章我们简要介绍了easylogging++的主要功能。easylogging++中有很多特性是通过宏来控制的,今天我们就来聊聊这些宏:debug输出流宏定义ELPP_INTERNAL_DEBUGGING......
  • 面向对象的三大特性
    ​ 面向对象的三大特性:封装:        我们把数据、一系列操作数据的函数封装到方法中,然后通过权限修饰符控制哪些方法可以让外知道,哪些只能自己知道,这样就能减少......
  • JWT有状态登陆与无状态登陆
    单点登录与JWTJWT 全称: JsonWebToken。作用: JWT的作用是 用户授权(Authorization) ,而不是用户的身份认证(Authentication) 。用户认证 指的是使用用户名、密码......
  • Docker学习笔记七:Docker提交镜像到阿里云仓库
    一、准备1、开启阿里云镜像仓库a.访问阿里云地址并登陆地址:http://cr.console.aliyun.comb.选择“容器镜像服务”c.使用“个人实例”构建仓库d.创建命名空......
  • Day20.1:关于this、super的解析
    this、super详解当我们在外部程序调用一个类的方法,如果这个类的方法与其父类的方法重载,我们需要用this、super进行区分this在Java中是一个复杂的关键字,this的使用形式体......