php使用Redis防多次重复请求

使用场景:在一些敏感操作上,比如:提现、兑换、购买

用户账户余额1000,黑客使用工具快速请求提现接口,导致账户余额判断失效,账号成负数

<?php

namespace ice;


/**
 * Redis Lock锁
 */
class Lock
{
    private static $_instance;
    public $_redis;

    private function __construct()
    {
        if (!extension_loaded('redis')) {
            throw new \Exception('not support: redis');
        }
        $this->_redis = new \Redis();
        $this->_redis->connect('127.0.0.1');
    }

    public static function getInstance()
    {
        if (self::$_instance instanceof self) {
            return self::$_instance;
        }
        return self::$_instance = new  self();
    }

    /**
     * 获取锁
     *
     * @param  String  $key     锁标识
     * @param  Int     $expire  锁过期时间
     *
     * @return Boolean
     */
    public static function lock($key, $expire = 5)
    {
        $objRedisConn = self::getInstance();
        //Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。
        //设置成功,返回 1 。 设置失败,返回 0 。
        $is_lock = $objRedisConn->_redis->setnx($key, time() + $expire);
        // 不能获取锁
        if (!$is_lock) {
            // 判断锁是否过期
            $lock_time = $objRedisConn->_redis->get($key);
            // 锁已过期,删除锁,重新获取
            if (time() > $lock_time) {
                $objRedisConn->unlock($key);
                $is_lock = $objRedisConn->_redis->setnx($key, time() + $expire);
            }
        }
        return $is_lock ? false : true;
    }

    /**
     * 释放锁
     *
     * @param  String  $key  锁标识
     *
     * @return Boolean
     */
    public static function unlock($key)
    {
        return self::getInstance()->_redis->del($key);
    }
}

使用方法:

1、Lock::lock($key); //上锁,如果已有锁返回真

2、Lock::unlock($key);  //不需要锁的时候,手动解锁

$key = 'lock_buy_' . $user->id;
if (Lock::lock($key)) {
    $this->error(__('请稍后再试'));
}

$order = Order::where(['status' => 0, 'id' => $id, 'user_id' => $user->id])->findOrEmpty();
if ($order->isEmpty()) {
     Lock::unlock($key);
     $this->error(__('参数错误'));
}
Lock::unlock($key);
$this->success(__('OK'));

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值