redis防止超售
方式一
redis在应用中越来越广泛, 其中常用的大部分操作都是非原子性的, 例如set
/get
/hmset
…这些会在多个操作时后边的覆写前边的, 例如
1 | graph LR |
请求前后先后进入, 几乎同时抵达数据库, 当A
检查时没有请求, B
先后到达,也检查到没有请求, 此时向redis
写入当前请求信息, A写入,B也写入了, 且会被后写入的覆盖, 无提示, 此时便达不到限制的目的, 而且如果秒杀场景下请求大的情况下, 一下进入的可能销售远远超过库存的数量.
此时就需要使用redis的原子性操作, 同时只能一个读写, 写入/读取有失败提示.setnx
/getset
setnx Key Value
设置一个键值, 如果同时写入只有一个会成功返回 1, 其余失败返回 0, 满足了并发加锁限制,getset Key NewValue
获取并设置一个值, 成功会返回当前设置的值,
如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 del Key
操作会导致把其他进程已获得 的锁释放掉
1 | // 函数封装 |
方式二
使用原子增减操作 incrby/decrby
, 下单时对数据进行增减, 优势无超长时间等待
如下: 简略代码
1 | const http = require('http'); |
此案例使用 单机redis
/ pm2 start app.js -i 4
/ ab -c 10 -n 100
多进程进行/多请求模拟操作.
示例如下:
- 多进程启动
1
$> pm2 start app.js -i 4
ab
工具模拟请求1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44$> ab -c 10 -n 100 http://127.0.0.1:3000/buy
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /buy/
Document Length: 0 bytes
Concurrency Level: 10
Time taken for tests: 0.031 seconds
Complete requests: 100
Failed requests: 0
Non-2xx responses: 94
Total transferred: 9286 bytes
HTML transferred: 0 bytes
Requests per second: 3180.16 [#/sec] (mean)
Time per request: 3.144 [ms] (mean)
Time per request: 0.314 [ms] (mean, across all concurrent requests)
Transfer rate: 288.39 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 1
Processing: 1 2 1.4 2 8
Waiting: 1 2 1.2 1 6
Total: 1 3 1.4 2 8
Percentage of the requests served within a certain time (ms)
50% 2
66% 2
75% 3
80% 3
90% 5
95% 6
98% 8
99% 8
100% 8 (longest request)pm2 log app
日志打印通过日志打印可以看出, 库存为7的时候, 有4个请求进入, 并且下单成功, 之后便没有了, 保证了库存安全1
2
3
4
5
6
7$> pm2 log app
...
2|app | 库存: 10, 购买: 3
2|app | 库存: 7, 购买: 3
0|app | 库存: 7, 购买: 1
0|app | 库存: 7, 购买: 1
0|app | 库存: 7, 购买: 2- 查看剩余库存
1
2$> curl http://localhost:3000/count
0
本文作者 : 萧逸雨
原文链接 : http://qiubo.ink/2020/12/25/redis防止超售/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!