PHP版滑动时间窗口算法
<?php
/**
* 作者:码农编程进阶笔记
* 点赞、分享朋友圈是最大的支持
*/
session_start();
$time = 60;//60秒
$count = 10; //可访问 10次
//第一次初始化
if(!isset($_SESSION['count'])){
$_SESSION['count'] = 1;
$_SESSION['time'] = time();
$_SESSION['cha'] = 0;
$_SESSION['status'] = 'success';
print_r($_SESSION);
}else {
$now = time();
$cha = $now - $_SESSION['time'];
$avg = intval($time / $count);//平均多少秒可获得一次机会
//如果超过次数
if($_SESSION['count'] > $count){
//如果时差超过平均可获得次数的时长
if($cha > $avg){
$_SESSION['count'] -= intval($cha / $avg); //计算可得多少次机会
$_SESSION['count'] = max($_SESSION['count'], 0);//修正次数不能为负。
$_SESSION['count']++;
$_SESSION['time'] = $now;
$_SESSION['cha'] = $cha;
$_SESSION['status'] = 'success';
print_r($_SESSION);
}else{
//如果时差没有超过 $avg ,则还是失败。
$_SESSION['cha'] = $cha;
$_SESSION['status'] = 'fail';
print_r($_SESSION);
}
}else{
//如果没超过次数正常访问
if($cha > $avg) {
$_SESSION['count'] -= intval($cha / $avg); //计算可得多少次机会
$_SESSION['count'] = max($_SESSION['count'], 0);//修正次数不能为负。
}
$_SESSION['count']++;
$_SESSION['time'] = $now;
$_SESSION['cha'] = $cha;
$_SESSION['status'] = 'success';
print_r($_SESSION);
}
}
如果要精确计算,则要记录每次访问以元素的形式记录时间戳,到数组,每次请求的时候,遍历数组元素中的时间戳,与当前时间比较,清理掉 N分钟之前的元素,然后再计算个数,如果个数没超,则允许,反之不行。
/**
* 滑动时间窗口
* 每次成功访问时,记录访问时间点
* 每次清理N分钟之前的访问时间点
* 对访问次数进行计数,判断是否超过次数
* 作者:码农编程进阶笔记
* @param $minute
* @param $count
* @param $times
* @return bool
*/
function timeWindow($minute, $count, &$times){
$now = time();
$point = $now - $minute * 60;//从当前时间往前推N分钟的时间点
foreach($times as $key => $item){
if($item < $point) unset($times[$key]); //把N分钟之前的访问清理掉
}
if(count($times) <= $count){
$times[] = $now; //成功时,记录本次访问时间点
return true;
}
return false;
}
赞赏码
非学,无以致疑;非问,无以广识