美文网首页
PHP+Redis高并发

PHP+Redis高并发

作者: LeeYaMaster | 来源:发表于2020-03-26 00:04 被阅读0次

初学Redis,于是便想写一个高并发的项目,最开始只能达到并发量1,后来增加并发,出现各种问题,我又采取各种办法来增大并发量,在慢慢增大并发量的过程中,我也在慢慢成长,在追求成功的过程中,越来越兴奋,成长的感觉,也是人生中最美妙的事情!
需求:一个抢课系统,使用Redis,course_1为课程的人数,user_1为哪些用户选择了课程,采用数组形式,由于ab压测,我不知道怎么传动态参数,于是我变用的随机数代替。
首先先来看代码:

            $redis = my_redis();
            if($redis->get('course_1') <= 0){
                $this->apiReturn(303,'课程已被抢完');
            }
            $redis->decr('course_1');
            $data = $redis->get('user_1');//获取key [value]
            $data = json_decode($data,JSON_UNESCAPED_UNICODE);
            array_push($data,mt_rand(1,100));
            $data = json_encode($data);
            $redis->getset('user_1',$data);
抢课人数结构 课程人数结构

第一次测试,总请求量100,同时并发量为1,课程人数100:

ab -n1000 -c50  http://127.0.0.1/lession_admin/public/index.php/api/test
-n一共多少次请求,-c瞬间的并发数
注意,localhost要改成127.0.0.1,不然会被积极拒绝(到底有多积极???)。
ab -n100 -c1  http://127.0.0.1/lession_admin/public/index.php/api/test
结果:课程数为0(正常)
[94,76,85,79,87...].length = 100(正常)

第二次测试,总请求量100,同时并发量为5,课程人数100:

结果:课程数为0(正常)
[94,76,85,79,87,32,64...].length = 95(异常)
我们发现少了5个人,那么会不会跟总请求量有关,于是我们改一下请求量

第三次测试,总请求量300,同时并发量为5,课程人数100:

结果:课程数为0(正常)
[94,76,85,79,87,32,64...].length = 89(异常)
很惊讶,每秒钟同时5的并发量,功能就已经产生异常了,这就得考虑代码问题了。

我们看到,每秒钟5个人访问,就出了问题,那么肯定是代码问题,我们看到,每次-1,这种思路不可取,非常容易出问题,于是我换一种思路,判断已经选课的人数,有没有超过总人数,如果超过了,就不能再选课,实验后发现,我这种做法是正确的,并且取得了很好的效果,Redis里的字符串(我刚开始因为看到可以自减,所以选择字符串结构,现在发现自己是错的),也改为了set结构,因为它有去重的功能:

            $courseId = 1;
            $id = I('id');
            $id = (int)$id;
            $redis = my_redis();
            这里的if是重点,判断人数100,有没有小于抢的人数,如果小于,那么就返回失败,这里是精华,之前自减1,真的太多漏洞了。
            if($redis->smembers('course_' . $courseId)[1] <= count($redis->smembers('user_' . $courseId))){
                $this->apiReturn(303,'课程已被抢完',["num"=>count($redis->smembers('user_1'))]);
            }
            $result = $redis->sismember('user_' . $courseId, $id);
            if ($result) {
                $this->apiReturn(304,'您不能重复抢课');
            }
            $result_Add = $redis->sadd('user_' . $courseId, $id);
            if ($result_Add) {
                $this->apiReturn(200,'抢课成功');
            }
            $this->apiReturn(305,'抢课失败');
课程信息 线程,一秒请求十万 随机变量1-500 http请求带参数 采用set结构,可以去重,在这个业务场景下,比list好用

第四次测试得出:

10000并发数据正常,也是100条数据,并没重复。
50000并发数据异常,超出3条数据,并没重复。
100000并发数据异常,超出1条数据,并没重复。
从并发量5异常,到并发量一万正常,就几行代码解决了这个问题,代码真的是很奇妙的东西。

搭建分布式:

我是用的windows搭建分布式,之前用Docker和Centos7搭建,一堆错误,原因找半天,挺麻烦的。参考教程,自己也搭建了起来:
https://blog.csdn.net/mydog520/article/details/81712897
https://blog.csdn.net/xiaobo060/article/details/80616718

redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385
检测
redis-trib.rb check 127.0.0.1:6379

如果说第二次启动报错的话,

错误信息为:
[ERR] Node 127.0.0.1:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

那么看这篇博客:
https://blog.csdn.net/wudalang_gd/article/details/52153571?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

下面我开始用分布式锁,来解决并发的问题。

相关文章

网友评论

      本文标题:PHP+Redis高并发

      本文链接:https://www.haomeiwen.com/subject/bzifuhtx.html