消息队列mysql redis那个好,redis可以做消息队列吗

b55995f74e47ddd42fbf77ac40db1e0c.png

应用场景:

例如秒杀。瞬时大量写入订单到数据库,导致数据库无法及时响应。此时可以采用Redis做消息队列,把所有需要写入的数据先写入Redis消息队列中,然后同时在服务器开启php-cli进程循环读取队列中的数据,异步写入数据库。使用redis做消息队列可能会出现消息丢失的情况,因为没有消息接收的确认机制。大型程序,应该使用类似RabitMQ来做专业消息队列。

1、使用publish/subscribe方式作为消息队列

特点:一个消息发布者(生产者),可以对应多个消息订阅者(消费者)。当消息发布到消息队列的时候,所有消息订阅者都可以收到消息。适用于分布式消息分发。client以阻塞的方式等待publish端的消息。多个消费者不能加快消息消费速度。

消息生产:$params =json_encode(['x_uid' => $x_uid, 'phone' => $phone]);

$redis->publish('test',$params); //test表示发布的频道名字

消息消费(php-cli模式运行):$redis = new Redis(); $redis->pconnect('127.0.0.1'); //必须用pconnect长连接

//设置redis连接永远不超时。默认60s超时断开连接 $redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

$redis->subscribe(array('test'), 'callback'); //test表示频道名字,callback 回调函数名

functioncallback($redis, $chan, $msg){ //对收到的消息进行处理函数

$params = json_decode($msg,true);

....

}

pconnect和connect区别:

connect:脚本结束之后连接就释放了。

pconnect:脚本结束之后连接不释放,连接保持在php-fpm进程中。

所以使用pconnect代替connect,可以减少频繁建立redis连接的消耗。

2、使用list作为redis消息队列

特点:一个消息生产者,对应一个消息消费者。多个消费者可以加快消息消费速度。

消息生产:$redis =newRedis();

$redis->connect('127.0.0.1');

//将需要写入数据库的数据全部push到队列(复杂数据可以先json编码成字符串)

$list = json_encode(['x_uid' => $x_uid, 'phone' => $phone, 'goods_id' => $goodsId,

'add_time' => time(), 'num_field' => $num_field]);

$redis->lpush('winer',$list);

注意:brpop消费数据如果没有成功写入数据库,会导致数据丢失。强烈要求生产数据时,二次备份到redis或文件中。

消息消费(php-cli模式运行):

注意:MySQL不主动关闭连接的情况下,一次连接最长八小时后自动断开。<?php

//链接数据库

$conn = mysqli_connect("localhost","root","root");

if(!$conn){

die("连接数据库失败:". mysqli_error());

}

mysqli_select_db($conn,"api");

//字符转换,读库

mysqli_query($conn,"set character set 'utf8'");

//写库

mysqli_query($conn,"set names 'utf8'");

//连接本地的 Redis 服务

$redis =newRedis();

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

//设置redis连接永远不超时。默认60s超时断开连接

$redis->setOption(Redis::OPT_READ_TIMEOUT,-1);

echo 'Listening...';

$i =1;

while(true){

$data = $redis->brpop('winer',0); // 0表示没有接收到参数的情况下,永远不超时断开

$info = json_decode($data[1],true);

$x_uid = $info['x_uid'];

$phone = $info['phone'];

$goods_id = $info['goods_id'];

$add_time = $info['add_time'];

$num_field = $info['num_field'];

//将数组写入数据库、订单

$sql = "insert into hd_hengda11_order (`x_uid`,`phone`,`goods_id`,`add_time`)

values ($x_uid,$phone,$goods_id,$add_time)"

$re = mysqli_query($conn,$sql);

echo $i.'_ok||';

$i++;

}

?>

其他:

秒杀场景防止商品超卖:

1、数据库中设置商品数量为无符号型,即不允许负数。当更新商品数量到负数时,返回false。

2、商品数量存在Redis的list队列中,每次抢购就pop删除一个元素出队列。//存放商品数量的队列

for($j =1; $j <=10; $j++){ /设置商品数量为10

$re =Redis::lpush(gooods_count,1);

}

判断商品数量逻辑$count=Redis::lpop('gooods_count');

//$count = Redis::llen('gooods_count'); //llen判断队列长度

if(!$count){

return'已经抢光了哦';

}

更多Redis相关知识,请访问Redis使用教程栏目!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值