【Java】-3种限流算法及实践

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 3种限流算法及实践

image.png

限流算法

  • 计数器算法 维护一个 counter,规定在单位时间内 counter 的大小不能超过最大值,每隔固定时间就将 counter 的值置零。如果这个 counter 大于设定的阈值,那么系统就拒绝请求
  • 漏桶算法
    image.png
  • 漏桶算法维护一个固定容量的桶,这个桶会按照指定的速度漏水。请求到达系统就类似于将水加入桶中,这个速度可以是匀速的也可以是瞬间的,如果这个桶满了,就会忽略后面的请求,直到这个桶可以存放多余的水。
    好处:可以将系统的处理能力维持在一个比较平稳的水平
    缺点:瞬间流量过来时,如果满了就会拒绝后面的请求流量
  • 令牌桶算法
    image.png令牌桶算法系统按照指定的速度往桶中添加 token,每来一个请求,就从桶里拿走一个 token,如果没有 token 就拒绝服务
    好处:控制系统的处理速度,通过统计信息实时优化令牌桶的大小
    与漏桶算法的区别:
    令牌桶算法由于在令牌桶里攒了很多令牌,因此在大流量到达的瞬间可以一次性将队列中所有的请求都处理完,然后按照恒定的速度处理请求
    漏桶算法是一直有一个恒等阈值,在大流量到达的时候,也会将多余的请求拒绝

限流实践

guava 的 concurrent 中有一个限流工具类 RateLimiter,其实现了单机限流,使用了令牌桶算法,它支持两种令牌获取接口:获取不到一直阻塞;在指定时间内获取不到就阻塞,超过这个时间就返回获取失败

  1. 使用 RateLimiter,单机限流
//初始化令牌桶大小,初始大小为2000
private RateLimiter ratelimiter = RateLimiter.create(2000);
public void process() {
 //获取令牌,获取不到就阻塞
 rateLimiter.acquire();
 //执行业务操作,例如写数据库
 bizLogic();
}

如果请求可以丢弃,防止大量请求过来耗尽系统资源,可以使用 tryAcquire()方法,和带超时的 tryAcquire(),在指定时间内获取不到令牌就返回 false

private RateLimiter rateLimiter = RateLimiter.create(2000);
if(rateLimiter.tryAcquire()) {
   doSomething();
} else {
   doSomethingElse();
}

RateLimiter 详细分析可见:https://www.jianshu.com/p/362d261115e7

  1. 使用 Redis, 分布式限流
    比如 1 秒内请求数量限制在 2000 内
  • 使用 Redis 实现计数器算法
    设置 redis 可以的过期时间为 1 秒,每次请求过来 value 加 1,如果 value 超过 2000 就拒绝访问,使用 Lua 脚本实现 incr 和 expire 的原子性
local key =KEYS\[1\]
local expire_time =ARGV\[1\]
local count =redis.call("INCR", key, 1)
if count == 1then
   redis.call("EXPIRE", key, expire_time)
end
return count
  • 使用 Redis 实现令牌桶算法
    使用 Redis 的 List 结构实现 定时任务执行,使用 rightPush 放入令牌,并保证令牌的唯一性
// 1S 的速率往令牌桶中添加 UUID,只为保证唯一性
@Scheduled(fixedDelay = 1000,initialDelay = 0)
public void setIntervalTimeTask(){
   redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
}

使用 leftPop 获取令牌

public Response limitFlow(Long id){
   Object result = redisTemplate.opsForList().leftPop("limit_list");
   if(result == null){
       return Response.ok("当前令牌桶中无令牌");
  }
   return Response.ok(articleDescription);
}
相关文章
|
23天前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
219 35
|
30天前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
1月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
机器学习/深度学习 算法 自动驾驶
395 0
|
2月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
3月前
|
运维 监控 算法
基于 Java 滑动窗口算法的局域网内部监控软件流量异常检测技术研究
本文探讨了滑动窗口算法在局域网流量监控中的应用,分析其在实时性、资源控制和多维分析等方面的优势,并提出优化策略,结合Java编程实现高效流量异常检测。
125 0
|
4月前
|
SQL 缓存 安全
深度理解 Java 内存模型:从并发基石到实践应用
本文深入解析 Java 内存模型(JMM),涵盖其在并发编程中的核心作用与实践应用。内容包括 JMM 解决的可见性、原子性和有序性问题,线程与内存的交互机制,volatile、synchronized 和 happens-before 等关键机制的使用,以及在单例模式、线程通信等场景中的实战案例。同时,还介绍了常见并发 Bug 的排查与解决方案,帮助开发者写出高效、线程安全的 Java 程序。
227 0
|
4月前
|
存储 搜索推荐 算法
Java 大视界 -- Java 大数据在智慧文旅旅游线路规划与游客流量均衡调控中的应用实践(196)
本实践案例深入探讨了Java大数据技术在智慧文旅中的创新应用,聚焦旅游线路规划与游客流量调控难题。通过整合多源数据、构建用户画像、开发个性化推荐算法及流量预测模型,实现了旅游线路的精准推荐与流量的科学调控。在某旅游城市的落地实践中,游客满意度显著提升,景区流量分布更加均衡,充分展现了Java大数据技术在推动文旅产业智能化升级中的核心价值与广阔前景。
|
4月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
134 0
|
4月前
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
203 1

热门文章

最新文章