redis商品秒杀源码php,PHP + Redis 实现商品秒杀实例

PHP + Redis 实现商品秒杀实例

前言

用原生PHP来实现商品的秒杀,实现的原理是,首先把所有的商品ID存进redis列表里,然后是一个把reids列表中商品ID取出来和用户ID绑定的过程。绑定成功也就是秒杀成功,秒杀成功的同时把用户ID和商品ID存进reids哈希表里。并记录秒杀失败的人数。

1.环境与技术

1.Nginx(Apache也行,目前我的服务器是Nginx)

2.PHP 5.6以上

3.Redis

4.压力测试工具ab

2.代码

2.1连接redis(redis.php)

为了省事,把连接redis的步骤写入一个文件里,没有密码的可以不写auth,这里选了redis索引为1的库,默认是redis索引为0的库。

$redis = new Redis();

$redis->connect('127.0.0.1',6379);

$redis->auth(password);

$redis->select(1);

2.2商品ID存入列表(crontab.php)

假设秒杀的商品有30件,把30件的商品ID都存进redis 列表里。

include_once "redis.php";

//设定商品数量

$count = 30;

$listKey = "goods_list";

for($i=1;$i<=$count;$i++){

//将商品id ,push到列表中

$redis->rpush($listKey,$i);

}

2.3 商品秒杀(kill.php)

这里的用户ID都是随机生成的,每请求一次都会生成一个唯一的用户ID和列表中的一个商品ID绑定,存进哈希表里。之后需要用压力测试工具ab模拟用户进场秒杀。

include_once "redis.php";

$uuid = md5(uniqid('user').time());

$listKey = "goods_list";

$orderKey = "buy_order";

$dailUserNum = "fail_num";

if($goodsId=$redis->lpop($listKey)){

//秒杀成功即存在redis的哈希列表中

$redis->hset($orderKey,$goodsId,$uuid);

}else{

//秒杀失败,记录失败用户个数,方便得知有效

$redis->incr($dailUserNum);

}

echo "SUCCESS";

3.操作

3.1 执行crontab.php文件

执行crontab.php文件,让商品ID存进redis列表。这个文件应该是一个定时任务定时执行的,现在我们手动执行一下。

% php /usr/local/var/www/redis/crontab.php

检测商品ID是否放入成功,连接redis客户端查看。

% redis-cli

127.0.0.1:6379> select 1

OK

127.0.0.1:6379[1]> lrange goods_list 0 -1

1) "1"

2) "2"

3) "3"

4) "4"

5) "5"

6) "6"

7) "7"

8) "8"

9) "9"

10) "10"

11) "11"

12) "12"

13) "13"

14) "14"

15) "15"

16) "16"

17) "17"

18) "18"

19) "19"

20) "20"

21) "21"

22) "22"

23) "23"

24) "24"

25) "25"

26) "26"

27) "27"

28) "28"

29) "29"

30) "30"

3.2.压力测试工具ab模拟秒杀

apache自带ab工具,我的是mac,mac自带apache,可以先检测一下

% ab --v

ab: wrong number of arguments

Usage: ab [options] [http[s]://]hostname[:port]/path

Options are:

-n requests Number of requests to perform

-c concurrency Number of multiple requests to make at a time

-t timelimit Seconds to max. to spend on benchmarking

This implies -n 50000

-s timeout Seconds to max. wait for each response

Default is 30 seconds

-b windowsize Size of TCP send/receive buffer, in bytes

-B address Address to bind to when making outgoing connections

-p postfile File containing data to POST. Remember also to set -T

-u putfile File containing data to PUT. Remember also to set -T

-T content-type Content-type header to use for POST/PUT data, eg.

'application/x-www-form-urlencoded'

Default is 'text/plain'

-v verbosity How much troubleshooting info to print

-w Print out results in HTML tables

-i Use HEAD instead of GET

-x attributes String to insert as table attributes

-y attributes String to insert as tr attributes

-z attributes String to insert as td or th attributes

-C attribute Add cookie, eg. 'Apache=1234'. (repeatable)

-H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'

Inserted after all normal header lines. (repeatable)

-A attribute Add Basic WWW Authentication, the attributes

are a colon separated username and password.

-P attribute Add Basic Proxy Authentication, the attributes

are a colon separated username and password.

-X proxy:port Proxyserver and port number to use

-V Print version number and exit

-k Use HTTP KeepAlive feature

-d Do not show percentiles served table.

-S Do not show confidence estimators and warnings.

-q Do not show progress when doing more than 150 requests

-l Accept variable document length (use this for dynamic pages)

-g filename Output collected data to gnuplot format file.

-e filename Output CSV file with percentages served

-r Don't exit on socket receive errors.

-m method Method name

-h Display usage information (this message)

-I Disable TLS Server Name Indication (SNI) extension

-Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)

-f protocol Specify SSL/TLS protocol

(TLS1, TLS1.1, TLS1.2 or ALL)

-E certfile Specify optional client certificate chain and private key

开始测试,100并发 1000访问量

% ab -c 100 -n 1000 http://localhost:8080/redis/kill.php

This is ApacheBench, Version 2.3

Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Completed 100 requests

Completed 200 requests

Completed 300 requests

Completed 400 requests

Completed 500 requests

Completed 600 requests

Completed 700 requests

Completed 800 requests

Completed 900 requests

Completed 1000 requests

Finished 1000 requests

Server Software: nginx/1.19.0

Server Hostname: localhost

Server Port: 8080

Document Path: /redis/kill.php

Document Length: 7 bytes

Concurrency Level: 100

Time taken for tests: 0.792 seconds

Complete requests: 1000

Failed requests: 0

Total transferred: 169000 bytes

HTML transferred: 7000 bytes

Requests per second: 1263.25 [#/sec] (mean)

Time per request: 79.161 [ms] (mean)

Time per request: 0.792 [ms] (mean, across all concurrent requests)

Transfer rate: 208.49 [Kbytes/sec] received

Connection Times (ms)

min mean[+/-sd] median max

Connect: 0 1 1.7 1 9

Processing: 16 73 10.8 76 84

Waiting: 16 73 10.8 76 84

Total: 25 74 9.3 77 86

Percentage of the requests served within a certain time (ms)

50% 77

66% 78

75% 78

80% 79

90% 80

95% 80

98% 81

99% 82

100% 86 (longest request)

4.效果

查看抢到商品的用户

127.0.0.1:6379[1]> hgetall buy_order

1) "1"

2) "722c8badaa1e2b53405672c9684d1822"

3) "2"

4) "e6820dd50508cd09cf65b03e928410d1"

5) "3"

6) "066097efb74efc587df98729bcff6418"

7) "5"

8) "1d077d9850abe2f99d0fd4b306de9149"

9) "4"

10) "bc2f8e8f9a2e77c315ace1bac5d48764"

11) "6"

12) "3f1647a2cc2b9ebe4d4af4d43d95bbc0"

13) "7"

14) "b71d278030b62a2972a7236cb4f51f9c"

15) "8"

16) "fec4dde48c48d5dbb617181e26c31cde"

17) "9"

18) "77760c6251e0c4c572789741899c12e0"

19) "11"

20) "e548411b6bc294dd1d10f96ca4d552c6"

21) "10"

22) "6d63a2ca724b3fdcc2f49f71ebf37c70"

23) "12"

24) "873521e8fdf465949dc8a48ded10ce5e"

25) "13"

26) "33e6cdb1df95219fd3e46d779591941b"

27) "14"

28) "033c644345628a13c45bab586af6d0e4"

29) "15"

30) "480afe21c920b0a02ebbe4c75f96b80b"

31) "16"

32) "87c79d0d1b448a4003785f6dde05ee3a"

33) "17"

34) "e6102eb6c4389074f0e7ebc0d574f0c9"

35) "18"

36) "719ee437a332d5a8f668474a6e204136"

37) "19"

38) "71d43aadafb97972bb2023119d80727f"

39) "20"

40) "875612b1b1a46088af7a79169b8a744f"

41) "22"

42) "c149527bfe7573f70c57e6eeef70483d"

43) "23"

44) "1bb2c03355b3f83b0106207a0ade98be"

45) "21"

46) "0cc81a86769d96f09ddf2388015cd8d8"

47) "24"

48) "a5ce3e992c6e36a0c692e317a356dfd9"

49) "25"

50) "9d92dad9a4c0212dd9cab0a9db169928"

51) "26"

52) "d37ee45647706d3e40a8cb8e78703782"

53) "27"

54) "399ac4d653541c74ef68620da86473a1"

55) "28"

56) "d00da588ff71dc46bab8a2efeacb4a0b"

57) "29"

58) "46550a2617e38508a0350bc6dfc95069"

59) "30"

60) "c9e97b821f8374c7ef37d38735f1ca74"

查看秒杀失败的人数

127.0.0.1:6379[1]> get fail_num

"970"

这时列表里的商品就空了

127.0.0.1:6379[1]> lrange goods_list 0 -1

(empty list or set)

5.注意

这过程可能会出现一些问题,

socket: Too many open files (24

lijiwei@lijiweideAir ~ % ab -c 100 -n 1000 http://localhost:8080/redis/kill.php

This is ApacheBench, Version 2.3

Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

socket: Too many open files (24)

解决方法:

看网上说是调整可以打开的文件数,操作一波

% ulimit -n 65535

ulimit: setrlimit failed: invalid argument

失败了,继续网上查阅,说是设置的数字特别大,可以用下面两个命令看下系统最大数

% sysctl kern.maxfiles

kern.maxfiles: 12288

% sysctl kern.maxfilesperproc

kern.maxfilesperproc: 10240

假如系统最大数字不满足你的要求,就修改下系统最大数,命令如下(数字自己设定,但是不要太大,有的电脑系统貌似有限定):

% sudo sysctl -w kern.maxfiles=65536

Password:

kern.maxfiles: 12288 -> 65536

% sudo sysctl -w kern.maxfilesperproc=65536

kern.maxfilesperproc: 10240 -> 65536

然后继续执行,就成功了

% ulimit -n 65535

2.apr_socket_recv: Connection reset by peer (54)

当我的并发量和访问人数比较大时,出现过这个问题,网上查了一些,但是没有解决,哪为大佬看到了请指教一下。

% ab -c 300 -n 3000 http://localhost:8080/redis/kill.php

This is ApacheBench, Version 2.3

Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

apr_socket_recv: Connection reset by peer (54)

Total of 1 requests completed

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值