时间戳转换工具

    限流算法在分布式领域是一个经常被提到的话题,当系统的处理能力有限时,如何阻止计划外的请求继续对系统试压,这是一个需要重视的问题。除了流量控制,限流还有一个应用目的是控制用户行为,避免垃圾请求。比如UGC社区、回复、点赞等行为都要严格受控,一般要严格限定某行为在规定内被允许的次数,超过了次数就是非法行为。对非法行为,业务必须适当的惩处策略。

    首先我们来看一个常见的、简单的限流策略。系统限定用户的某个行为在限定时间内只能允许发生N次,如何来实现这个限流功能?
1.) 写入cookie,通过cookie值来判断,当然用户可以通过客户端来修改,不严谨
2.) 写入session
几种redis实现的限流,也是今天的重点:

3.) redis-计数器

说明:在一段时间间隔内,处理请求的数量固定的,超的就不做处理。 比如每分钟限制操作10,如果在每分钟的59s来操作接口,那限制在第十分钟的时候才生效,因为每次操作设置存活时间会重置存活时间。可以用于预防别人刷接口。如果想再过去一段时间内限制多少次,可以看4.)

public function SpeedCounter()
{
$redis = ZFactory::getRedis('public');

// 最大请求数量
$maxCount = 10;

$redis_key = 'zcont';

// 每分钟内,一个用户只能访问10次
$interval = 60;
// 请求总数量
$zcount = $redis->get($redis_key);

// 判断是否超过最大值
if ($zcount <= $maxCount) {
//业务处理

$redis->incr($redis_key);
$redis->Expire($redis_key, $interval);

} else {
// 记录错误日志

// 返回错误提示
}
}

4.) 时间窗口算法
    通过redis的zSet属性做滑动窗口,可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,value相同则是更新score,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求


其中每一小个表示 10s,被红色虚线包围的时间段则为需要判断的时间间隔,比如 60s 秒允许 100 次请求,那么红色虚线部分则为 60s 。

tp5 Demo 

public function getShortLink()
{
$key = 'key';

$binding_time = 60 * 10;
// 十分钟内十次请求
$end_time = time();
$start_time = $end_time - $binding_time;
// redis句柄
$header = Cache::init()->handler();
// 获取一段时间内的请求数
$array_num = $header->zRangebyscore($key, $start_time, $end_time);
// 删除时间范围外的缓存,减少内存暂用
$header->zremrangeByScore($key, 1, $start_time - 1);
if (count($array_num) >= 10) {
// 记录错误日志
// 返回错误提示
}

// 业务处理

// 增加一次操作记录
$header->zAdd($key, time(), create_uuid()); # value不重要,需要保持唯一,用uuid
}

5.) 漏桶算法


说明:漏斗算法是最常见的限流方法之一。如果将漏嘴堵住,然后一直灌水,它就会变满,直至再也装不下了。 如果将漏嘴放开,水就会往下流,流走一部分,就又可以继续往里面灌水。如果漏嘴灌水的速度大于灌水的速度,那么漏斗永远装不满。 反之漏斗水满了,灌水就要暂停,并等待一段时间。
    redis 4.0提供了一个限流redis模块,它叫Redis-Cell。该模块也是用漏斗算法,并提供了原子的限流命令。该模块只有一个命令,cl.throttle
6.)令牌算法


    在令牌桶算法中有一个程序以某种恒定的速度生成令牌,并存入令牌桶中,而每个请求需要先获取令牌才能执行,如果没有获取到令牌的请求可以选择等待或者放弃执行。

    Google 开源的 guava 包,提供思路,可以百度了解

联系我们 - 首页 - 关于我们
Copyright © 2017-2022 iteam. All Rights Reserved. Current version is 2.50.0.
粤ICP备17021424号
VV:34190 UV:110862 PV:357035