使用Redis加鎖的方式可以防止重複操作,包括表單提交,ajax等http請求,它的原理就是redis的incr命令給鍵自增,如果傳回值不是1,就表示是重複請求,具體看代碼:
| 代碼如下 |
複製代碼 |
/** * 鎖定請求 * @param int $expire 鎖定時間 * @param string $mark 自訂標籤 * @return bool */ protected function lock($expire=1,$mark=''){ $url=strtolower(MODULE_NAME.'/'.ACTION_NAME);//操作地址 $prefix='lock_';$sid=$_COOKIE[C("SESSION_OPTIONS.name")]; $key=$prefix.md5($sid.$url.$mark);//令牌索引值 /** * @var Redis $redis */ $redis = D('Redis'); if($redis->incr($key)==1){ return $redis->expire($key,$expire); } return false; } |
這裡也要講講Redis的incr命令的用法:
INCR key命令用法
將 key 中儲存的數字值增一。
如果 key 不存在,那麼 key 的值會先被初始化為 0 ,然後再執行 INCR 操作。
如果值包含錯誤的類型,或字串類型的值不能表示為數字,那麼返回一個錯誤。
本操作的值限制在 64 位元(bit)有符號數字表示之內。
| 代碼如下 |
複製代碼 |
redis> SET page_view 20 OK redis> INCR page_view (integer) 21 redis> GET page_view # 數字值在 Redis 中以字串的形式儲存 "21" |
傳回值是incr之後的值。
如果incr一個不存在的鍵,它會自動建立這個鍵並傳回值1.
expire 命令樣本:
expire key 22
設定鍵名為key(必須存在)的到期時間為22s.
再回到開始處定義的lock方法,索引值為lock+當前操作地址+cookie值+自訂字串,進行incr操作並使用expire命令設定到期時間預設1s,如是是第一次請求會返回1(expire設定緩衝成功),表示設定緩衝時間成功,否則返回false表示重複請求或操作。
使用的時候:
| 代碼如下 |
複製代碼 |
if(!$this->lock(1)){ //重複操作了 } |
這樣就可以判斷是重複操作了。
| 代碼如下 |
複製代碼 |
$this->unlock()
|
這樣就解鎖了,可以允許第二次一樣的提交。
看看解鎖方法:
| 代碼如下 |
複製代碼 |
/** * 解鎖請求 * @param string $mark 自訂標籤 * @return bool */ protected function unlock($mark=''){ $url=strtolower(MODULE_NAME.'/'.ACTION_NAME);//操作地址 $prefix='lock_';$sid=$sid=$_COOKIE[C("SESSION_OPTIONS.name")]; $key=$prefix.md5($sid.$url.$mark);//令牌索引值 /** * @var Redis $redis */ $redis = D('Redis'); return $redis->del($key); } |
這裡使用了Redis的del命令。