PHP 中Lua嵌入redis
Posted Json2011315
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP 中Lua嵌入redis相关的知识,希望对你有一定的参考价值。
Lua 嵌入 Redis 优势:
- 减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;
- 原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;
- 复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.
注意:
首先要了解redis事务是不会滚的,所以在lua中嵌入多条redis执行,只是保证多条redis具有原子操作(不是mysql事务的原子性哦),原子操作指的是多条命令执行成功就是成功,其中一条执行就会失败,但是成功执行的redis命令不会回滚
编写php代码
redis_lua.php
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
/*
模拟场景下单支付成功需要操作的redis:
1.扣减redis锁定的库存
2.添加redis待发货库存
3.添加redis商品销量
4.减少redis可销量库存
原始redis缺点:
1.命令多次发送,消耗IO
*/
/*
php引入lua脚本:https://www.php.net/manual/zh/book.lua.php
PHP引入lua方式执行redis原因:
1.减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;
2.原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;
3.复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.
需要注意的是:
redis事务地址:https://blog.csdn.net/baidu_23086307/article/details/80461668?utm_source=blogxgwz7
首先要了解redis事务是不会滚的,所以在lua中嵌入多条redis执行,只是保证多条redis具有原子操作(不是mysql事务的原子性哦),原子操作指的是多条命令执行成功就是成功,其中一条执行就会失败,但是成功执行的redis命令不会回滚
*/
/*
先手动在redis中添加锁定库存,待发货单库存,销量,可销量
mset STOCK_LOCK_KEY 10 STOCK_FREEZE_KEY 0 GOODS_VALUME_KEY 0 STOCK_SALE_KEY 10
*/
/**
* 地址:https://www.php.net/manual/zh/lua.eval.php
* @param $lua_redis 第一个参数 lua中嵌入redis的字符串
* @param $stock_lock redis锁定的库存的key
* @param $stock_lock_num 需要操作的锁定库存
*
* @param $stock_freeze redis待发货库存的key
* @param $stock_freeze_num 需要操作的待发货库存
*
* @param $goods_volume redis商品销量key
* @param $goods_valume_num 需要操作的商品销量
*
* @param $stock_sale redis可销量库存key
* @param $stock_sale_num 需要操作的可销量
*
* @param $key_value_numbers 键值对数值
*/
//操作的数量
$goods_num=6;
$stock_lock='STOCK_LOCK_KEY';
$stock_lock_num=$goods_num;
$stock_freeze="STOCK_FREEZE_KEY";
$stock_freeze_num=$goods_num;
$goods_volume="GOODS_VALUME_KEY";
$goods_valume_num=$goods_num;
$stock_sale="STOCK_SALE_KEY";
$stock_sale_num=$goods_num;
//lua 嵌入redis
$lua_redis=<<<SCRIPT
local stock_lock=KEYS[1]
local stock_freeze=KEYS[2]
local goods_volume=KEYS[3]
local stock_sale=KEYS[4]
local stock_lock_num=ARGV[1]
local stock_freeze_num=ARGV[2]
local goods_volume_num=ARGV[3]
local stock_sale_num=ARGV[4]
local stock_lock_res=redis.call("DECRBY",stock_lock,stock_lock_num)
local stock_freeze_res=redis.call("INCRBY",stock_freeze,stock_freeze_num)
local goods_volume_res=redis.call("INCRBY",goods_volume,goods_volume_num)
local stock_sale_res=redis.call("DECRBY",stock_sale,stock_sale_num)
return stock_freeze_res
SCRIPT;
//键值对数值
$key_value_numbers=4;
$paramsArr=array($stock_lock,$stock_freeze,$goods_volume,$stock_sale,$stock_lock_num,$stock_freeze_num,$goods_valume_num,$stock_sale_num);
$res = $redis->eval($lua_redis,$paramsArr,$key_value_numbers);
var_dump($res);
进入redis-cli客户端,先添加数据
127.0.0.1:6379> mset STOCK_LOCK_KEY 10 STOCK_FREEZE_KEY 0 GOODS_VALUME_KEY 0 STOCK_SALE_KEY 10
OK
127.0.0.1:6379> keys *
1) "STOCK_FREEZE_KEY"
2) "GOODS_VALUME_KEY"
3) "STOCK_SALE_KEY"
4) "STOCK_LOCK_KEY"
127.0.0.1:6379>
php cli方式执行redis_lua.php
[root@localhost phpwww]# php redis_lua.php
int(6)
redis-cli客户端,查看数据
127.0.0.1:6379> mget STOCK_LOCK_KEY STOCK_FREEZE_KEY GOODS_VALUME_KEY STOCK_SALE_KEY
1) "4"
2) "6"
3) "6"
4) "4"
以上是关于PHP 中Lua嵌入redis的主要内容,如果未能解决你的问题,请参考以下文章