1、本系列文章每期都將解決一個Redis實際問題
2、每期問題將在每期的評論中選取
3、問題限Redis相關,其它問題如果本人感興趣也不排除開闢新系列
4、本人常用PHP所以解決方案以PHP為主
5、評論裡沒有合適的提問時我會自己給自己出題
問題描述:
本期為第一期,所以只能自己出題了
如何用Redis給訂單限流,如每M秒允許N個訪問
解決方案:
<?php
/**
* 是否允許放行
* @param string $key redis鍵字首
* @param int $timeInterval 時間間隔(秒)
* @param int $max 時間間隔內最大放行數
* @return bool 是否放行
* @throws Exception
* @example
* <pre>
* //每秒放行一個
* isAllow('my_allow');
*
* //每秒放行3個
* isAllow('my_allow',1,3);
*
* //每3秒放行2個
* isAllow('my_allow',3,2);
*/
function isAllow(string $key, int $timeInterval=1, int $max=1):bool{
if($timeInterval<1){
throw new Exception('時間間隔必須大於0');
}
if($max<1){
throw new Exception('最大放行數必須大於0');
}
$redis=new Redis();
$redis->connect('192.168.31.187');
if(!$redis->isConnected()){
throw new Exception('Redis服務連線失敗');
}
//對時間戳取模,使得每$timeInterval秒取得同一個時間戳
$time=time();
$key.=':'.($time-($time%$timeInterval));
//自增並返回自增後的結果
$index=$redis->incr($key);
//如果是第一個訪問,設定鍵的過期時間
if($index===1){
$redis->expire($key,$timeInterval+1);
}
return $index<$max+1;
}
程式碼解讀:
- 對時間取模,使得鍵名每
$timeInterval
秒更新一次 incr()
方法自增鍵的值,如果鍵不存在則先建立一個值為0
的鍵再進行自增- 根據自增原理,同鍵名下第
N
次自增返回的值就是N
- 鍵名每
$timeInterval
秒更新一次,所以在建立鍵的$timeInterval+1
秒後鍵就不再有價值
以上,歡迎大家提問
、糾錯
、補充
、最佳化
本作品採用《CC 協議》,轉載必須註明作者和本文連結