redis的高级应用(原子性、expired、mq)
我们在项目中经常会用到nosql来储存访问率高的数据,大多数就是用redis,凭借着比mysql高得多的qps支持数,这样做确实能提高处理速度。那么,redis就只能用来做数据存储查询吗?当然不是!redis还有很多功能等待使用。
一、原子性:
面对高并发抢购的场景,单用mysql记录来判断库存很容易发生超卖的情况。这时候我们可以利用redis decr原子性做锁,实现防止超卖。
1)使用decr方式:
<?php $redis = new Redis(); $redis->connect(localhost, 6379); $key = stock; $data = $redis->decr($key); if ($data>0){ header(HTTP/1.1 200 success); echo success; }else{ header(HTTP/1.1 400 Not Found); echo false; }
2)使用读取重构方式:
<?php $redis = new Redis(); $redis->connect(localhost, 6379); $key = stock;//redis数据库key [注:默认redis数据库选择第0号数据库] $data = $redis->get($key); $data = $data - 1; $redis->set($key, $data, 600); if ($data>0){ header(HTTP/1.1 200 success); echo success; }else{ header(HTTP/1.1 400 Not Found); echo false; }
我们预先设置stock=200,然后模拟1000并发请求持续性30秒。
1)
2)
从测试结果可以看到,第一种方式执行结果是正确199次,而第二种方式成功814次出现了大量的超卖,如果是在实际的产品中,后果不堪设想。
二、expired过期事件
redis有ttl属性,当数据超过了livetime自动销毁时会触发事件,我们可以监控这个事件来进行业务处理。比如新订单有三十分钟支付时间,我们就设置订单的ttl为30min,过期事件修改订单为取消状态;又比如,一场线上考试定时两小时,我们就设置ttl为2h,事件触发结束考试。
具体监控 redis expired过期事件的使用方法可以看一下我的另一篇文章
三、消息队列
无可否认redis队列对比起其他专门的消息队列如rabbitmq、activemq等是弱了点,从可选的部署模式、消息的丢失率都是差一点的,但是胜在小巧。当你需要消息队列,但不想多装的软件,而且消息的必要性又不高,这时候请选择redis的消息队列。
consummer
<?php fuction listen(){ $redis = new Redis(); $redis->connect(’localhost‘,6379); $redis->auth(123456); $key = mq_;//redis数据库key [注:默认redis数据库选择第0号数据库] while(1) { //从队列最前头取出一个值 $mq_message = $redis->lPop($key); //TODO 自定义处理 var_dump($mq_message); } } listen();
producer
<?php $redis = new Redis(); $redis->connect(’localhost‘,6379); $redis->auth(123456); $key = mq_;//redis数据库key [注:默认redis数据库选择第0号数据库] $redis->rPush($key, hello mq); //关闭redis连接 $redis->close();
先cli模式运行consummer,fpm模式运行producer测试推入队列。
下一篇:
gorm使用中遇到的坑点