利用Redis实现统计24小时内的访问量

需求

我们这里的需求是,记录不同用户在24小时(指定时间)内的访问量,并记录访问日志。如果达到一定的频率则封禁IP

测试环境

Redis 6.2.4
PHP 8.0

开始

我们先来了解一下Redis,Redis是一个高性能的Key => Value缓存器,由于数据缓存在内存中,所以比Mysql等数据库等响应速度要快几十到上百倍。

在这个实例中,我们用到的是Redis的Hash类型,通过用户每次访问,在Redis中记录访问者的IP以及对应的时间戳,来达到统计的目的,并且判断该IP访问的历史时间戳是否超过了24小时,如果超过则删除,最终通过llen来获取24小时内的访问次数。

首先我们通过PHP连接Redis:

1
2
3
4
5
6
7
8
9
10
11
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis -> select(1); //选择DB1
} catch (Exception $e) {
header('Content-type:text/json');
header('Access-Control-Allow-Origin: *');
header('ERROR: redis -> ' . $e->getMessage());
echo json_encode(array('code' => 444,'msg' => '系统错误,请联系管理员')); // redis连接失败
exit;
}

接着可以通过$_SERVER['REMOTE_ADDR']等函数获取 访问者ip,获取访问者IP之后,我们需要在Redis中检查这个键是否存在,如果不存在则需要新建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$redis_key_name = 用户IP;
if($redis -> exists($redis_key_name)){
while(True) {
//检查历史访问的时间戳是否过期,过期则删除
$da = $redis -> lRange($redis_key_name,0,1)[0] ?? '';
if(time() - (int)$da >= $limit_time){
$redis -> lrem($redis_key_name,$da,0);
} else {
break;
}
}
//写入当前时间戳
$redis -> rPushx($redis_key_name,time());
$num = $redis -> llen($redis_key_name);
} else {
$redis -> lPush($redis_key_name,time());
$num = 1;
}

之后我们可以直接使用llen获取表内的数据个数:

1
2
3
4
5
6
if($redis -> llen($redis_key_name) >= $limit_num){
//超过限制数目 -> banip
}
$redis -> expire($redis_key_name,$limit_time); //这里用来设置键的有效期 ,超过24小时则删除

//同时可以通过error_log()函数记录用户的访问信息

demo