成都企业网站公司wordpress 媒体播放
成都企业网站公司,wordpress 媒体播放,有了网站开发app是不是更容易,wordpress布局插件固定时间窗口算法
固定时间窗口算法也可以叫做简单计数算法。网上有很多都将计数算法单独抽离出来。但是笔者认为计数算法是一种思想#xff0c;而固定时间窗口算法是他的一种实现包括下面滑动时间窗口算法也是计数算法的一种实现。因为计数如果不和时间进行绑定的话那么失去…固定时间窗口算法
固定时间窗口算法也可以叫做简单计数算法。网上有很多都将计数算法单独抽离出来。但是笔者认为计数算法是一种思想而固定时间窗口算法是他的一种实现包括下面滑动时间窗口算法也是计数算法的一种实现。因为计数如果不和时间进行绑定的话那么失去了限流的本质了。就变成了拒绝了 优点
在固定的时间内出现流量溢出可以立即做出限流。每个时间窗口不会相互影响在时间单元内保障系统的稳定。保障的时间单元内系统的吞吐量上限
缺点
正如图示一样他的最大问题就是临界状态。在临界状态最坏情况会受到两倍流量请求除了临界的情况还有一种是在一个单元时间窗内前期如果很快的消耗完请求阈值。那么剩下的时间将会无法请求。这样就会因为一瞬间的流量导致一段时间内系统不可用。这在互联网高可用的系统中是不能接受的。
实现 Autowiredprivate StringRedisTemplate redisTemplate;// 固定时间窗口算法GetMapping(/start)public MapString, Object start(RequestParam MapString, Object paramMap) {//根据前端传递的qps上线int times 100;if (paramMap.containsKey(times)) {times Integer.parseInt(paramMap.get(times).toString());}String redisKey redisQps;RedisAtomicInteger redisAtomicInteger new RedisAtomicInteger(redisKey, Objects.requireNonNull(redisTemplate.getConnectionFactory()));int no redisAtomicInteger.getAndIncrement();//设置时间固定时间窗口长度 1Sif (no 0) {redisAtomicInteger.expire(1, TimeUnit.SECONDS);}//判断是否超限 time2 表示qps3log.info(no值-{},no);if (no times) {throw new RuntimeException(qps refuse request);}log.info(times值-{},times);//返回成功告知MapString, Object map new HashMap();map.put(success, success);return map;}测试 滑动时间窗口算法
滑动时间窗口算法是一种限流算法其原理是记录一段时间内的请求数量并根据时间窗口的滑动来判断是否接受新的请求。该算法通过维护一个滑动窗口来记录时间窗口内的请求数量并根据窗口的大小和限流阈值来决定是否接受新的请求。
滑动时间窗口算法的实现方式相对复杂一些但相对于固定时间窗口算法更加灵活和精确。在滑动时间窗口算法中时间窗口是不断滑动的每个窗口的大小和起点可以根据实际需求进行配置。同时该算法也支持动态调整限流阈值和流量控制粒度能够更好地应对流量波动和突发请求的情况。
滑动时间窗口算法的核心思想是通过维护一个时间窗口内的请求计数器并根据时间窗口的滑动来判断是否接受新的请求。具体来说当一个新的请求到达时算法会根据当前时间点判断该请求属于哪个时间窗口并更新对应窗口的计数器。如果计数器已经达到了限流阈值则拒绝该请求否则接受该请求。随着时间的推移时间窗口会不断滑动并更新计数器的值。
滑动时间窗口算法相对于固定时间窗口算法更加灵活和精确能够更好地应对流量波动和突发请求的情况。同时该算法也支持动态调整限流阈值和流量控制粒度能够更好地满足实际需求。在实际应用中需要根据具体情况选择适合的限流算法来控制流量。
优点
滑动时间窗口算法的优点主要包括以下几点
灵活性和可配置性强滑动时间窗口算法的时间窗口大小和起点可以根据实际需求进行配置同时限流阈值也可以动态调整这使得算法能够更好地应对流量波动和突发请求的情况。精度高滑动时间窗口算法相对于固定时间窗口算法更加精确因为它考虑了时间窗口内的请求数量和时间点能够更好地反映请求的实际情况。支持多维度限流滑动时间窗口算法可以支持多维度的限流例如根据IP地址、用户ID、接口等不同维度进行限流这使得算法能够更加精细地控制流量。
缺点
然而滑动时间窗口算法也存在一些缺点
实现复杂度高滑动时间窗口算法的实现相对复杂需要维护一个滑动窗口来记录时间窗口内的请求数量并不断更新窗口的值这需要耗费更多的计算和存储资源。内存占用大由于滑动时间窗口算法需要记录每个时间窗口内的请求数量和时间点因此需要占用更多的内存资源。无法平滑地实现请求流量的控制滑动时间窗口算法只能通过控制时间段来控制请求总量无法平滑地实现请求流量的控制这可能会影响到用户体验和系统的稳定性。
实现
滑动时间窗口是将时间更加细化上面我们是通过redis#setnx实现的。这里我们就无法通过他统一记录了。我们应该加上更小的时间单元存储到一个集合汇总。然后根据集合的总量计算限流。redis的zsett数据结构就和符合我们的需求。为什么选择zset呢因为redis的zset中除了值以外还有一个权重。会根据这个权重进行排序。如果我们将我们的时间单元及时间戳作为我们的权重那么我们获取统计的时候只需要按照一个时间戳范围就可以了。因为zset内元素是唯一的所以我们的值采用uuid或者雪花算法一类的id生成器
// 滑动时间窗口算法GetMapping(/startList)public MapString, Object startList(RequestParam MapString, Object paramMap) {String redisKey qpsZset;Integer times 100;if (paramMap.containsKey(times)) {times Integer.valueOf(paramMap.get(times).toString());}long currentTimeMillis System.currentTimeMillis();long interMills 10000L;Long count redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis);// 检查QPSQueries Per Second是否超过限制/*** 使用System.currentTimeMillis()获取当前时间戳。* 设置一个时间间隔interMills为1000毫秒即1秒。* 使用redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis)查询过去1秒内Redis ZSet中指定键redisKey的数量。这个数量会被赋值给count变量。* 如果count的值大于times则抛出一个运行时异常表示QPS超过限制*/if (count times) {throw new RuntimeException(qps refuse request);}redisTemplate.opsForZSet().add(redisKey, UUID.randomUUID().toString(), currentTimeMillis);MapString, Object map new HashMap();map.put(success, success);return map;}漏桶算法
漏桶算法是一种常用于流量控制和限流的算法其核心思想是将突发流量整形以便为网络提供一个稳定的流量。
漏桶算法可以看作是一个带有常量服务时间的单服务器队列如果漏桶包缓存溢出那么数据包会被丢弃。在网络中漏桶算法可以控制端口的流量输出速率平滑网络上的突发流量实现流量整形从而为网络提供一个稳定的流量。
漏桶算法的实现相对简单不需要复杂的数据结构或计算易于理解和部署。其优点包括平滑处理流入系统的请求以恒定的速率将请求处理释放从而避免了突发请求对系统的冲击控制精度高可以通过调整漏桶的出水速率来精确地控制请求的处理速度适用于需要平滑处理流量和避免突发请求的场景例如网络流量控制、防止DDOS攻击等。
然而漏桶算法也存在一些缺点例如请求延迟可能导致某些请求的响应时间变长不适用于实时性要求高的场景因为请求需要按照恒定速率进行处理无法满足即时性要求无法应对突发流量因为漏桶的出水速率是固定的无法根据流量的变化进行动态调整。 优点
面对限流更加的柔性不在粗暴的拒绝。增加了接口的接收性保证下流服务接收的稳定性。均匀下发
实现 // 漏桶算法GetMapping(/startLoutong)public MapString, Object startLoutong(RequestParam MapString, Object paramMap) {String redisKey qpsList;Integer times 100;if (paramMap.containsKey(times)) {times Integer.valueOf(paramMap.get(times).toString());}Long size redisTemplate.opsForList().size(redisKey);// 检查队列长度是否超过限制if (size times) {throw new RuntimeException(qps refuse request);}// 添加请求到队列Redis列表的右侧。Long aLong redisTemplate.opsForList().rightPush(redisKey, String.valueOf(paramMap));if (aLong times) {//为了防止并发场景。这里添加完成之后也要验证。 即使这样本段代码在高并发也有问题。此处演示作用// 修剪Redis列表使其长度为timesredisTemplate.opsForList().trim(redisKey, 0, times - 1);throw new RuntimeException(qps refuse request);}MapString, Object map new HashMap();map.put(success, success);return map;}模拟消费
Component
Slf4j
public class SchedulerTask {Autowiredprivate StringRedisTemplate redisTemplate;Scheduled(cron */5 * * * * ?)private void process() {//一次性消费两个log.info(正在消费。。。。。。);String redisKey qpsList;redisTemplate.opsForList().trim(redisKey, 2, -1);}}测试 令牌桶算法
令牌桶和漏桶法是一样的。只不过将桶的作用方向改变了一下。漏桶的出水速度是恒定的如果流量突然增加的话我们就只能拒绝入池但是令牌桶是将令牌放入桶中我们知道正常情况下令牌就是一串字符当桶满了就拒绝令牌的入池但是面对高流量的时候正常加上我们的超时时间就留下足够长的时间生产及消费令牌了。这样就尽可能的不会造成请求的拒绝最后不论是对于令牌桶拿不到令牌被拒绝还是漏桶的水满了溢出都是为了保证大部分流量的正常使用而牺牲掉了少部分流量
实现 // 令牌桶算法GetMapping(/startLingpaitong)public MapString, Object startLingpaitong(MapString, Object paramMap) {String redisKey lingpaitong;String token redisTemplate.opsForList().leftPop(redisKey);//正常情况需要验证是否合法防止篡改if (StringUtils.isEmpty(token)) {throw new RuntimeException(令牌桶拒绝);}MapString, Object map new HashMap();map.put(success, success);return map;}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/87611.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!