多线程压力测试 介绍_redis队列 和 秒杀应用 + 压力测试介绍

1.简述

redis队列一般用于缓解数据库压力 ,诸如秒杀,邮件群发,消息推送等等

redis的加入能很好的 帮助系统中 各个模块解耦。

而Redis不仅可作为缓存服务器,还可用作消息队列。它的列表类型天生支持用作消息队列。如下图所示:

ccac084413b974b76e31353b5663e60a.png

对于服务器减少io 压力 有一定的帮助

2.秒杀的原理

86df000711012db40d4cba15bd482c13.png

秒杀基本原理比较简单

用户点击抢购按钮 -> 把uid 和时间存入redis的队列中 -> 服务器中有一个入库程序不停轮询redis队列是否有数据 -> 如果有存入数据库

这里面有2点需要注意一下:

1. 插入队列的时候 ,需要判断库传,不能出现多插入

2. 在入库的时候 如果出现数据插入失败的情况 需要进行回滚

3.秒杀的代码实现

用户操作秒杀:

header("Content-type: text/html; charset=utf-8");
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
​
$redis_name= "miaosha";
//库存
$nums = 10;
//用户id
$user_id = $_GET['uid'];
if(($redis->llen($redis_name)) <  $nums ){
    $redis->lpush($redis_name,json_encode(array('uid'=>$user_id,'time'=>microtime())));
    echo $user_id."秒杀成功!";
    exit();
}else{
    echo "秒杀失败!";
    exit();
}
$redis->close();

后台处理秒杀队列:

header("Content-type: text/html; charset=utf-8");
error_reporting(E_ALL);
require_once './db.php';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
​
$redis_name = "miaosha";
​
//数据库
$configs =array('host'=>'127.0.0.1','port'=>'3306','user'=>'***','passwd'=>'','dbname'=>'test');
$mysql = new MMysql($configs);
​
//处理开始
while ($count = $redis->lLen($redis_name)) {
    $task = $redis->rpop($redis_name);
 
    $taskdata = json_decode($task, true);
    $data = array(
        'uid'=>$taskdata['uid'],
        'time'=>$taskdata['time'],
    );
​
 $rs = $mysql->insert('redis',$data);
 if(!$rs){
     //由于我们是在右边取,所以如果数据插入失败了要从左边放回去(重新排队),以免影响队列中其他元素的处理
     $redis->lpush($redis_name,$task);
     echo "处理失败<br>";
 }else{
     echo "处理成功<br>";
 }
 
 sleep(1);
}
​
$redis->close();

4.关于redis里的锁

4.1 先说一下乐观锁

乐观锁,顾名思义,乐观的认为数据不会被修改,只有当更新时才去判断数据是否被修改过,通常用版本号或时间戳来实现。

redis中的事务通过watch和multi来实现。

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)

$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
 
 //
$tnums = $redis->get('goods_stock_nums');
​
//设置商品的库存
if($tnums==0){
    echo "活动已经结束,明天请早end!";
    exit();
}
​
//监视该key
$redis->watch('goods_stock_nums');
​
//sleep(5);
//开启事务
$redis->multi();
 
//修改库存数
$redis->decr('goods_stock_nums');
 
//提交事务,如果在此期间有其他请求修改了该key,那么事务会失败
if ($redis->exec()) {
    echo '抢购成功suc';
} else {
    echo '数据错误,请重新再试fail';
}

可以看到我在程序中加入了sleep(5) 这行代码。

这是方便我在客户端去实验

0d109140f4c0ff518e673e4076a68a6b.png

如果我在运行上面这段代码过程中,我用客户端修改了这个值。

那么上面这段代码就会失败,返回 数据错误,请重新再试fail

4.2 再说一下 悲观锁

待续更新..

5.关于apache自带的压力测试工具 ab

ab是apache自带的一款功能强大的测试工具

安装了apache一般就自带了,

用法可以查看它的说明 。

参数众多,一般我们用到的是-n 和-c
ab.exe -c 2 -n 10 http://127.0.0.1/test/2020hash.php

-n 表示并发一共请求10次

-c 表示并发量为2,模拟2个线程 , 2个 客户 , 这个数必须小于 -n 。 (因为如果这里我设置 -c 为 11 , 那就是11个客户 ,只发了10次请求 ,这样做是没有意义的 ,况且apache也会给你报错)

-c的增大 意味着对服务器 访问压力的增大 , 就好比 2个人 同时抢拿 晒在地上的10个硬币, 有可能会同时2个人拿到同一个硬币 。

我们说回redis这里 , 我们设置goods_stock_nums 初始是11次 , 通过对程序测试

ab.exe -c 12 -n 12 http://127.0.0.1/test/2020hash.php 剩余1次

ab.exe -c 4 -n 12 http://127.0.0.1/test/2020hash.php 剩余2次

那就是说 -c 12的时候 ,成功了 10次, 有2次返回 <数据错误,请重新再试fail>

-c 4的时候 成功了 9次 , 有3次返回 <数据错误,请重新再试fail>

当我们把-n 设置成20 的时候 ,剩余次数就0了

请允许我加个友友情链接: http://www.sdmarrys.com

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值