redis rua解决库存问题_库存秒杀问题-redis解决方案- 接口限流

/**

* 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 keys = Collections.singletonList(ip);

List 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做接口限流

1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...

基于注解的接口限流+统一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.秒杀.抢购促销等,这些都是典型的大流量高并发场景.关于秒杀,小伙伴们可以参见我的另一篇 ...

Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流

最近管点闲事浪费了不少时间,感谢网友libinwalan的留言提醒.及时纠正路线,继续跟大家一起学习Spring Cloud Alibaba. Nacos作为注册中心和配置中心的基础教程,到这里先告一 ...

SpringCloud(8)---zuul权限校验、接口限流

zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...

Spring Cloud(7):Zuul自定义过滤器和接口限流

上文讲到了Zuul的基本使用: https://www.cnblogs.com/xuyiqing/p/10884860.html 自定义Zuul过滤器: package org.dreamtech.a ...

Guava的RateLimiter实现接口限流

最近开发需求中有需要对后台接口进行限流处理,整理了一下基本使用方法. 首先添加guava依赖: com.google.guava&l ...

随机推荐

linux kernel 0.11 bootsect

bootsect作用 ①将自己移动到0x90000处 ②将setup从磁盘读到0x90200处 ③将system从磁盘读到0x10000处 寄存器 汇编代码中存在:数据段data seg 栈段 sta ...

Qt实现应用程序单实例运行--LocalServer方式

使Qt应用程序能够单实例运行的典型实现方法是使用共享内存实现.该方法实现简单,代码简洁. 但有一个致命缺陷:共享内存(QSharedMemory)实现的单程序运行,当运行环境是UNIX时,并且程序不幸 ...

C#各版本特性

C# 2.0 泛型,可空类型,匿名方法,更方便的委托,迭代器,分布类型,静态类,包含不同访问修饰符的属性的取值和赋值方法,命名空间别名,pragma指令,固定大小的缓冲器. C# 3.0 LINQ,自 ...

php+jquery+ajax+json的一个最简单实例

html页面:

你可能感兴趣的:(redis,rua解决库存问题)