
前言
本文是秒杀系统的第二部分. 它将解释实际代码,以帮助您快速了解尖峰系统的关键点并开始实际项目.
本文主要介绍接口电流限制措施. 实际上,接口电流限制也非常广泛地定义. 接口电流限制本身也是系统安全保护的一种措施. 我将简要列出这些易于理解的类型:
此外,在上一篇文章之后,许多学生提出了“严重抗议”,即高并发度时并不能出售所有商品,因此在本文中我将解释乐观和悲观性的锁.
项目的源代码在这里,妈妈不再需要担心阅读本文:
面对大量并发的请购请求时,如果不限制接口的电流,可能会对后台系统造成很大的压力. 尤其是对于下订单的接口,太多请求到达将影响系统的稳定性.
因此,尖峰系统将尝试尽可能独立于公司的其他后端系统进行部署,以免影响尖峰系统崩溃到其他系统.
除了独立部署峰值服务外,我们所能做的就是尝试让后台系统以稳定,优雅的方式处理大量请求.

上有很多关于令牌桶限流算法的介绍,我摘录了一个介绍:
令牌桶算法最初源自计算机网络. 在网络上传输数据时,为了防止网络拥塞,必须限制从网络流出的流量,以便以相对均匀的速度发送流量. 令牌桶算法实现了此功能,可以控制发送到网络的数据量,并允许突发数据的传输.
固定大小的令牌桶可以自己以恒定速率生成令牌. 如果令牌没有被消耗,或者消耗速率小于生成速率,则令牌将继续增加,直到存储桶被填充. 稍后生成的令牌将从存储桶中溢出. 在最后一个存储桶中可以保存的最大令牌数量将永远不会超过存储桶的大小.

漏桶算法非常简单. 水(请求)首先进入漏水桶. 漏水的桶以一定的速度放水. 当进水量太大时,会直接溢出. 可以看出,漏桶算法可以强制数据传输. 率.

不能将令牌桶算法与另一个常见算法(泄漏桶算法)相混淆. 这两种算法的主要区别是:
泄漏存储桶算法可以强制限制数据传输速率,令牌存储桶算法除了平均数据传输速率之外,还可以允许一定程度的突发传输. 在令牌桶算法中,只要令牌桶中有令牌,它就允许突发传输数据,直到达到用户配置的阈值为止,因此适用于具有突发特征的流量.

Guava是Google的开源Java工具类,涵盖了所有内容. 它还提供了RateLimiter类,该类实现了令牌桶算法.
我们拿出了源代码,并将令牌桶电流限制代码添加到了我们之前讨论的乐观锁捕捉界面中:
OrderController:
@Controller
public class OrderController {
private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);
@Autowired
private StockService stockService;
@Autowired
private OrderService orderService;
//每秒放行10个请求
RateLimiter rateLimiter = RateLimiter.create(10);
@RequestMapping("/createWrongOrder/{sid}")
@ResponseBody
public String createWrongOrder(@PathVariable int sid) {
int id = 0;
try {
id = orderService.createWrongOrder(sid);
LOGGER.info("创建订单id: [{}]", id);
} catch (Exception e) {
LOGGER.error("Exception", e);
}
return String.valueOf(id);
}
/**
* 乐观锁更新库存 + 令牌桶限流
* @param sid
* @return
*/
@RequestMapping("/createOptimisticOrder/{sid}")
@ResponseBody
public String createOptimisticOrder(@PathVariable int sid) {
// 阻塞式获取令牌
//LOGGER.info("等待时间" + rateLimiter.acquire());
// 非阻塞式获取令牌
if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
LOGGER.warn("你被限流了,真不幸,直接返回失败");
return "购买失败,库存不足";
}
int id;
try {
id = orderService.createOptimisticOrder(sid);
LOGGER.info("购买成功,剩余库存为: [{}]", id);
} catch (Exception e) {
LOGGER.error("购买失败:[{}]", e.getMessage());
return "购买失败,库存不足";
}
return String.format("购买成功,剩余库存为:%d", id);
}
}
在代码中,RateLimiter rateLimiter = RateLimiter.create(10);在这里,令牌桶类被初始化,每秒释放10个请求.
在界面中,您可以看到有两种使用方法:
我们使用JMeter设置200个线程以同时在中抢购100部iPhone. (结构和JMeter的使用请从头开始构建一个简单的秒杀系统(1): 防止超卖)
我们将分别断言该请求,该请求的响应结果是“您受到限制,不幸的是,它直接返回失败”:


我们使用rateLimiter.tryAcquire(1000,TimeUnit.MILLISECONDS)(一种非阻塞令牌桶算法)来查看购买结果:

您可以看到绿色的请求代表令牌桶截获的请求,红色的代表成功购买订单的请求. 通过JMeter的请求摘要报告,我们可以知道在这种情况下,请求不能被限制在15%左右.

可以看出,由于乐观锁定,在200个不受当前限制的请求中,并发更新失败会带来一些问题,从而导致产品无法销售. 这也是上一篇文章中朋友最常问的问题. 所以我想谈谈乐观锁定和悲观锁定.
在讨论锁之前,让我们再次尝试阻止令牌桶算法的使用. 我们将代码更改为rateLimiter.acquire();然后将还原到100个库存,并清除订单表. 开始请求:
这次结果非常有趣. 首先放置一些结果图(按顺序截屏). 有思想的学生可以首先推测我接下来要说什么.





摘要:
本文不再介绍令牌桶的实现原理令牌桶算法google,它仍然基于实际作战.
毕竟,Guava仅提供令牌桶的实现. 在实际项目中,必须根据需要使用它或由您自己实现. 您可以看一下这篇文章:
在讨论令牌桶限流算法之后,让我们回到超卖问题. 在大量请求的情况下,如果像第一篇文章中那样使用乐观锁,它将导致大量请求返回. 经验非常差.
但是,如果使用悲观锁,例如事务,则可以让一个一个地处理库存编号修改,然后在修改成功后满足下一个请求,因此在不同情况下,应使用根据实际情况进行悲观锁定和乐观锁定.
顾名思义令牌桶算法google,悲观锁(Pessimistic Lock)是非常悲观的. 每次去获取数据时,您都认为其他人会对其进行修改,因此,每次获取数据时,数据都会被锁定,从而其他人将阻止该数据. 直到获得锁. 在传统的关系中使用了许多这样的锁定机制,例如行锁定,表锁定,读取锁定,写入锁定等,它们在执行操作之前就被锁定了.
顾名思义,乐观锁非常乐观. 每次去获取数据时,我都认为其他人不会修改它,因此不会被锁定,但是在更新时,我会判断在此期间是否还有其他人. 要更新此数据,可以使用版本号机制. 乐观锁适用于多读取应用程序类型,可以提高吞吐量. 例如,如果提供了类似于write_condition机制的机制,则它们都是乐观锁.
这两种类型的锁各有优缺点. 您不能简单地定义哪个比哪个更好.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-199594-1.html
#吴亦凡##吴亦凡1106生日快乐#新歌
为什么韩国出专辑一定要把头发弄的五颜六色
还在这充好人