库存秒杀问题-redis解决方案- 接口限流
<?php
/**
* Created by PhpStorm.
* redis 销量超卖秒杀解决方案
* redis 文档:http://doc.redisfans.com/
* ab -n 10000 -c 3000 http://localhost/demo.php 模拟并发
*/ $redis = new Redis();
$redis->connect('127.0.0.1',6379); //1. 对某一个键加锁,这个键是我们自己设置,起到监视作业
$redis->watch('sales'); //获取销量,清空sales 为0
$sales = $redis->get('sales'); //总库存
$store = 4; if($sales>=$store){
exit('已经被抢光了'); //跳转活动结束页面
} //redis事务不会回滚, 开启事务
$redis->multi();
$redis->set('sales',$sales+1); //销量加1
$res = $redis->exec(); if($res){
//减库存
include db.php; //数据库连接
//执行sql ,减库存
}
exit; =====================redis接口限流============================
- 非脚本实现
private boolean accessLimit(String ip, int limit, int time, Jedis jedis) {
boolean result = true;
String key = "rate.limit:" + ip;
if (jedis.exists(key)) {
long afterValue = jedis.incr(key);
if (afterValue > limit) {
result = false;
}
} else {
Transaction transaction = jedis.multi();
transaction.incr(key);
transaction.expire(key, time);
transaction.exec();
}
return result;
}
以上代码有两点缺陷
- 可能会出现竞态条件: 解决方法是用
WATCH
监控rate.limit:$IP
的变动, 但较为麻烦; - 以上代码在不使用
pipeline
的情况下最多需要向Redis请求5条指令, 传输过多.
Lua脚本实现
Redis 允许将 Lua 脚本传到 Redis 服务器中执行, 脚本内可以调用大部分 Redis 命令, 且 Redis 保证脚本的原子性:
- 首先需要准备Lua代码: script.lua
--
-- Created by IntelliJ IDEA.
-- User: jifang
-- Date: 16/8/24
-- Time: 下午6:11
-- local key = "rate.limit:" .. KEYS[]
local limit = tonumber(ARGV[])
local expire_time = ARGV[] local is_exists = redis.call("EXISTS", key)
if is_exists == then
if redis.call("INCR", key) > limit then
return
else
return
end
else
redis.call("SET", key, )
redis.call("EXPIRE", key, expire_time)
return
end
private boolean accessLimit(String ip, int limit, int timeout, Jedis connection) throws IOException {
List<String> keys = Collections.singletonList(ip);
List<String> argv = Arrays.asList(String.valueOf(limit), String.valueOf(timeout)); return 1 == (long) connection.eval(loadScriptString("script.lua"), keys, argv);
} // 加载Lua代码
private String loadScriptString(String fileName) throws IOException {
Reader reader = new InputStreamReader(Client.class.getClassLoader().getResourceAsStream(fileName));
return CharStreams.toString(reader);
}
Lua 嵌入 Redis 优势:
- 减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;
- 原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;
- 复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.
库存秒杀问题-redis解决方案- 接口限流的更多相关文章
- Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流
1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...
- SpringBoot使用自定义注解+AOP+Redis实现接口限流
为什么要限流 系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用.为了避免这种情况,我们就需要对接口请求进行限流. 所以 ...
- 基于注解的接口限流+统一session认证
代码心得: 一个基本的做法:对于用户身份认证做到拦截器里,针对HandlerMethod进行统一拦截认证,根据方法上的注解标识,判别是否需要身份验证,并将查找出来的User实体存入ThreadLoca ...
- 【Dnc.Api.Throttle】适用于.Net Core WebApi接口限流框架
Dnc.Api.Throttle 适用于Dot Net Core的WebApi接口限流框架 使用Dnc.Api.Throttle可以使您轻松实现WebApi接口的限流管理.Dnc.Api.Thr ...
- 限流(三)Redis + lua分布式限流
一.简介 1)分布式限流 如果是单实例项目,我们使用Guava这样的轻便又高性能的堆缓存来处理限流.但是当项目发展为多实例了以后呢?这时候我们就需要采用分布式限流的方式,分布式限流可以以redis + ...
- 【高并发】亿级流量场景下如何为HTTP接口限流?看完我懂了!!
写在前面 在互联网应用中,高并发系统会面临一个重大的挑战,那就是大量流高并发访问,比如:天猫的双十一.京东618.秒杀.抢购促销等,这些都是典型的大流量高并发场景.关于秒杀,小伙伴们可以参见我的另一篇 ...
- Guava-RateLimiter实现令牌桶控制接口限流方案
一.前言 对于一个应用系统来说,我们有时会遇到极限并发的情况,即有一个TPS/QPS阀值,如果超了阀值可能会导致服务器崩溃宕机,因此我们最好进行过载保护,防止大量请求涌入击垮系统.对服务接口进行限流可 ...
- 服务限流 -- 自定义注解基于RateLimiter实现接口限流
1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...
- Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流
最近管点闲事浪费了不少时间,感谢网友libinwalan的留言提醒.及时纠正路线,继续跟大家一起学习Spring Cloud Alibaba. Nacos作为注册中心和配置中心的基础教程,到这里先告一 ...
随机推荐
- yii2 Gridview网格小部件
Gridview 网格小部件 一.特点: 1.是yii中功能最强大的小部件之一: 2.非常适合快速建立系统的管理后台. 3.用 dataProvider 键来指定数据的提供者 4.用 filterMo ...
- idea快捷键列表
Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关闭文件 C ...
- C#多线程技术提高RabbitMQ消费吞吐率
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的第二部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理 ...
- Python计算分位数
Python计算分位数 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/gdkyxy2013/article/details/80911514 ...
- EF Core中执行Sql语句查询操作之FromSql,ExecuteSqlCommand,SqlQuery
一.目前EF Core的版本为V2.1 相比较EF Core v1.0 目前已经增加了不少功能. EF Core除了常用的增删改模型操作,Sql语句在不少项目中是不能避免的. 在EF Core中上下文 ...
- 与临时对象的斗争(上)ZZ
C++ 是一门以效率见长的语言(虽然近来越来越多的人“不齿”谈及效率,我深以为不然,在某一次的程序编写中不对效率锱铢必较并不意味意味着我们就不应该追求更多的更好的做法).总之吧,相比起其它语言,程序员 ...
- 命令 上传项目到git中
点击Clone or dowload会出现一个地址,copy这个地址备用. 接下来就到本地操作了,首先右键你的项目,如果你之前安装git成功的话,右键会出现两个新选项,分别为Git Gui Here, ...
- 9 月份 GitHub 上最火的 JavaScript 开源项目!
推荐 GitHub 上9 月份最受欢迎的 10 个 JavaScript 开源项目,在这些项目中,你有在用或用过哪些呢? 1.基于 Promise 的 HTTP 客户端 Axios https://g ...
- Java代码质量监控工具Sonar安装
1. 代码质量七宗罪 Sonar是一个代码质量管理系统.它的帮助文档开篇明义,提出了代码质量的七宗罪.总结的比較到位.最好还是一看: 1. Bug和隐藏Bug(Bugs and Pot ...
- [转]恕我直言,在座的各位根本不会写 Java!
导语 自 2013 年毕业后,今年已经是我工作的第 4 个年头了,总在做 Java 相关的工作,终于有时间坐下来,写一篇关于 Java 写法的一篇文章,来探讨一下如果你真的是一个 Java 程序员,那 ...