1、本系列文章每期都將解決一個(gè)Redis實(shí)際問題
2、每期問題將在每期的評論中選取
3、問題限Redis相關(guān),其它問題如果本人感興趣也不排除開辟新系列
4、本人常用PHP所以解決方案以PHP為主
5、評論里沒有合適的提問時(shí)我會自己給自己出題
問題描述:
本期為第一期,所以只能自己出題了
如何用Redis給訂單限流,如每M秒允許N個(gè)訪問
解決方案:
<?php /** * 是否允許放行 * @param string $key redis鍵前綴 * @param int $timeInterval 時(shí)間間隔(秒) * @param int $max 時(shí)間間隔內(nèi)最大放行數(shù) * @return bool 是否放行 * @throws Exception * @example * <pre> * //每秒放行一個(gè) * isAllow('my_allow'); * * //每秒放行3個(gè) * isAllow('my_allow',1,3); * * //每3秒放行2個(gè) * isAllow('my_allow',3,2); */ function isAllow(string $key, int $timeInterval=1, int $max=1):bool{ if($timeInterval<1){ throw new Exception('時(shí)間間隔必須大于0'); } if($max<1){ throw new Exception('最大放行數(shù)必須大于0'); } $redis=new Redis(); $redis->connect('192.168.31.187'); if(!$redis->isConnected()){ throw new Exception('Redis服務(wù)連接失敗'); } //對時(shí)間戳取模,使得每$timeInterval秒取得同一個(gè)時(shí)間戳 $time=time(); $key.=':'.($time-($time%$timeInterval)); //自增并返回自增后的結(jié)果 $index=$redis->incr($key); //如果是第一個(gè)訪問,設(shè)置鍵的過期時(shí)間 if($index===1){ $redis->expire($key,$timeInterval+1); } return $index<$max+1; }
代碼解讀:
-
對時(shí)間取模,使得鍵名每$timeInterval秒更新一次
-
incr()方法自增鍵的值,如果鍵不存在則先創(chuàng)建一個(gè)值為0的鍵再進(jìn)行自增
-
根據(jù)自增原理,同鍵名下第N次自增返回的值就是N
-
鍵名每$timeInterval秒更新一次,所以在創(chuàng)建鍵的$timeInterval+1秒后鍵就不再有價(jià)值
以上,歡迎大家提問、糾錯(cuò)、補(bǔ)充、優(yōu)化。
推薦:《PHP視頻教程》