日常的开发工作中,经常会遇到诸如发送一封邮件这样比较耗时的业务需求,用户往往需要等邮件发送完毕才能进行下一步动作,整个业务流程被发送邮件这个耗时的动作阻塞了,这时往往需要解耦业务,即把耗时的作业单独剥离出去,用户无需等待处理结果,服务端会直接返回,以便用户下一步操作,而剥离出去的业务会单独在另一个子系统慢慢运行。
有很多队列式的产品来解耦业务需求,但是如果你的系统中已经部署了Redis,并且业务量不是很大的话可以尝试使用Redis的发布订阅模式来满足你的需要,但是要十分注意的是,如果你的业务量较大,并且数据产生的速率很快,数据消耗的速度赶不上数据产生速度的话,最好是采用专业的消息队列产品来实现(比如activeMq,rocketMq等)。
因为笔者发现Redis的消息堆积的天花板上限很低,稍不留神就会溢出,然后会自动断开消费客户端的连接,造成消费进程假死(即使进程没有被关闭,也依旧不再消费数据),并且Redis也十分缺乏对此类业务的监控工具,造成运维难度直线式上升。——故如果在有其他可选项的情况下,不要轻易在生产服务上部署这种方案,这里仅作为技术层面作一介绍
Redis的发布订阅模式可以简单分为发布数据端(生产者)和订阅数据端(消费者)两部分,发布侧写入数据到称为“频道”的数据通道中之后便会立即返回,然后订阅侧在监控到有数据产生后,便会拿到这个数据进行下一步的业务操作。这里使用php作为实现语言来对这一功能进行说明
<?php
/** 消费者代码 **/
set_time_limit(0);
ini_set('default_socket_timeout', -1); //保持连接
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$result = $redis->auth('password');
//var_dump($result);
$redis->subscribe(array('channel'),function($instance, $channelName, $message){
if($channelName == 'channel'){
callback($message);
}
});
?>
<?php
/** 生产者代码 **/
$redis = new Redis();
$result = $redis->connect('127.0.0.1',6379);
$result = $redis->publish('channel','hi Redis');
dump($result);
?>