'lock' => [
'keyPrefix' => 'lock:', //Redis锁定 key 前缀
'timeOut' => 3, //Redis锁定超时时间,单位为秒
],

// 设置锁定的过期时间
$time = time();
$lockKey = Yii::$app->params['lock']['keyPrefix'] . 'game_category';
$lockExpire = $time + Yii::$app->params['lock']['timeOut'];

// 获取 Redis 连接,以执行相关命令
$redis = Yii::$app->redis;

// 获取锁定
$executeCommandResult = $redis->setnx($lockKey, $lockExpire);

// 返回0,表示已经被其他客户端锁定
if ($executeCommandResult == 0) {
// $fileName = microtime(true);
// file_put_contents('./../runtime/0-' . $fileName . '.txt', '1');
// 防止死锁,获取当前锁的过期时间
$lockCurrentExpire = $redis->get($lockKey);
// $fileName = microtime(true);
// file_put_contents('./../runtime/6-' . $fileName . $lockCurrentExpire . '.txt', '1');
// 判断锁是否过期,如果已经过期
if ($time > $lockCurrentExpire) {
// $fileName = microtime(true);
// file_put_contents('./../runtime/1-' . $fileName . '.txt', '1');
// 释放锁定
// $redis->del($lockKey);
// 获取锁定
// $executeCommandResult = $redis->setnx($lockKey, $lockExpire);
// 防止并发锁定,检查存储在 key 的旧值是否仍然是过期的时间戳,如果是,则获取锁定,否则返回假
$executeCommandResult = $redis->getset($lockKey, $lockExpire);
if ($lockCurrentExpire != $executeCommandResult) {
// $fileName = microtime(true);
// file_put_contents('./../runtime/2-' . $fileName . '.txt', '1');
return ['status' => false, 'code' => 0, 'message' => ''];
}
// $fileName = microtime(true);
// file_put_contents('./../runtime/3-' . $fileName . '.txt', '1');
}
// 返回0,表示已经被其他客户端锁定,且不存在死锁,返回假
if ($executeCommandResult == 0) {
// $fileName = microtime(true);
// file_put_contents('./../runtime/4-' . $fileName . '.txt', '1');
return ['status' => false, 'code' => 0, 'message' => ''];
}
}
// $fileName = microtime(true);
// file_put_contents('./../runtime/5-' . $fileName . '.txt', '1');

















// 设置锁定的过期时间,获取相关锁定参数
$time = time();
$lockKey = Yii::$app->params['lock']['keyPrefix'] . 'game_category';
$lockExpire = $time + Yii::$app->params['lock']['timeOut'];
// 获取 Redis 连接,以执行相关命令
$redis = Yii::$app->redis;
// 获取锁定
$executeCommandResult = $redis->setnx($lockKey, $lockExpire);
// 返回0,表示已经被其他客户端锁定
if ($executeCommandResult == 0) {
// 防止死锁,获取当前锁的过期时间
$lockCurrentExpire = $redis->get($lockKey);
// 判断锁是否过期,如果已经过期
if ($time > $lockCurrentExpire) {
// 防止并发锁定,检查存储在 key 的旧值是否仍然是过期的时间戳,如果是,则获取锁定,否则返回假
$executeCommandResult = $redis->getset($lockKey, $lockExpire);
if ($lockCurrentExpire != $executeCommandResult) {
return ['status' => false, 'code' => 0, 'message' => ''];
}
}
// 返回0,表示已经被其他客户端锁定,且不存在死锁,返回假
if ($executeCommandResult == 0) {
return ['status' => false, 'code' => 0, 'message' => ''];
}
}

<pre class="wp-block-syntaxhighlighter-code">
<?php namespace common\models\redis; use Yii; /** * This is the model class for table "{{%lock}}". * */ class Lock extends \yii\redis\ActiveRecord { /** * Redis模型的锁定实现 * @param string $lockKeyName 锁定键名 * 格式如下: * * 'game_category' //锁定键名,如比赛分类 * * @return integer 成功返回对象数组/失败返回错误信息 * 格式如下: * * [ * 'status' => true //状态
* ]
*
* 或者
*
* [
* 'status' => false, //状态
* 'code' => 0, //返回码
* 'message' => '', //说明
* ]
*
*/
public function lock($lockKeyName)
{
// 设置锁定的过期时间,获取相关锁定参数
$time = time();
$lockKey = Yii::$app->params['lock']['keyPrefix'] . $lockKeyName;
$lockExpire = $time + Yii::$app->params['lock']['timeOut'];
// 获取 Redis 连接,以执行相关命令
$redis = Yii::$app->redis;
// 获取锁定
$executeCommandResult = $redis->setnx($lockKey, $lockExpire);
// 返回0,表示已经被其他客户端锁定
if ($executeCommandResult == 0) {
// 防止死锁,获取当前锁的过期时间
$lockCurrentExpire = $redis->get($lockKey);
// 判断锁是否过期,如果已经过期
if ($time > $lockCurrentExpire) {
// 防止并发锁定,检查存储在 key 的旧值是否仍然是过期的时间戳,如果是,则获取锁定,否则返回假
$executeCommandResult = $redis->getset($lockKey, $lockExpire);
if ($lockCurrentExpire != $executeCommandResult) {
return ['status' => false, 'code' => 0, 'message' => ''];
}
}
// 返回0,表示已经被其他客户端锁定,且不存在死锁,返回假
if ($executeCommandResult == 0) {
return ['status' => false, 'code' => 0, 'message' => ''];
}
}
}
/**
* Redis模型的释放锁定实现
* @param string $lockKeyName 锁定键名
* 格式如下:
*
* 'game_category' //锁定键名,如比赛分类
*
* @return integer 被删除的keys的数量
* 格式如下:
*
* 1 //被删除的keys的数量
*
* 或者
*
* 0 //被删除的keys的数量
*
*/
public function unlock($lockKeyName)
{
// 获取相关锁定参数
$lockKey = Yii::$app->params['lock']['keyPrefix'] . $lockKeyName;
// 获取 Redis 连接,以执行相关命令
$redis = Yii::$app->redis;
// 释放锁定
return $redis->del($lockKey);
}
}
</pre>


/* Redis模型的锁定实现 */
$lockKeyName = 'game_category';
$lock = new Lock();
$lockResult = $lock->lock($lockKeyName);
// 返回 false,表示已经被其他客户端锁定
if ($lockResult['status'] === false) {
return ['status' => false, 'code' => 0, 'message' => ''];
}



PHP / Laravel / Yii2 老项目维护与长期技术支持
如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。
适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护
可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查
如需咨询,请联系我,并注明:PHP 维护咨询。
联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

发表回复