while($w_status){
try{// $user_repay_id = $redis->rpop($lpush_key);
$user_repay = $redis->brpop($lpush_key,55);
$user_repay_id = $user_repay[1];
if(empty($user_repay_id)){
$redis->del('repay_make_judge')
$w_status = false;$redis->close();
break;
}$db_status = M('user_repay', 'jr_finance_')->where(array('user_repay_id' => $user_repay_id))->getField('db_status');
if($db_status==20){
$return = $this->repaymentHandelDatacommon($user_repay_id);
$return =json_decode($return,true);
if($return['status']==0){
throw new Exception($user_repay_id.$return['info']);
}
}else{
sleep(10);
}
}catch (Exception $e){
cunguan_log('记录还款队列数据出错@@@',$e->getMessage());
}
}
上面的代码处理标红的那一段,其他的部分就可以是一个队列处理消息的过程了,我相信大部分人用redis处理队列都是这样的;就是一个简单的while循环,判断队列里面是否有值,有就处理,但是这样有一个问题,要是这样这个进程会一直运行,在nginx上会导致502的错误;(当然通过配置可避免);但是这样始终是非常消耗性能的,一般有点经验的人都知道这样是不可取的,所以我们会这样在队列的消息处理完后会结束循环,然后用个定时任务来定时跑这个方法,这样性能会好点,但是这样还会有个问题,这样会导致消息处理的不及时,而且消息会集中在某一个时间段;
我们理想的肯定是在队列里面有消息就处理,没消息程序就停止,这里大家可以用rabbitmq,这个是我觉得比较好用的,但是这个相对redis来说复杂一点,那接下来我说一下我用redis处理的方式:首先大家每次在入列的时候,都异步请求一个判断该队列是否在处理的方式;记住是异步请求,要是同步的就达不到队列的效果了;方法如下:
$redis = $this->redisLink();
//设置锁值
$lockExpire = 7200;
$lockValue = time() + $lockExpire;
$lock = $redis->setnx('repay_make_judge', '1');
//判断锁是否存在以及防止死锁
if (!empty('repay_make_judge') || ($redis->get('repay_make_judge') < time() && $redis->getSet('repay_make_judge', '1')) < time())) {
//给锁设置生存时间
$redis->expire('repay_make_judge', $lockExpire);
$this->refundpop();
} else {
exit;
}
上面代码的大概意思就是,每次消息入列是都会检测repay_make_judge是否存在,不存在就会执行消息队列处理的方法,如果存在就不处理;这个就可以达到实时的检测队列的消息,又不会有多余的请求,记住在处理消息队列的函数里消息处理完后需要删除repay_make_judge;让下次队列有数据是能启动消息队列;