linux任务队列设计,Linux下Redis+crontab实现任务队列

前段时间由于一个控制方法要实现的逻辑任务太多了,无论怎么优化都还是有瓶颈。网上介绍可以使用任务队列的机制,把一些不是立即需要相应的逻辑处理放在队列中,让某个程序时时去执行。举个例子:用户上来我的网站注册,注册完后,我需要给用户的邮箱帐号推送一些邮件,这个推送邮件所发的时间可能远比注册保存用户资料所花的时间多些,也不是立即就需要响应到前端给客户知道。所以,是可以把推送邮件这一动作作为一个任务添加到队列中。

说明下我测试调试的环境是在Ubuntu12.04下的,安装redis和添加crontab命令是通过终端命令的,我测试的项目是基于yii框架,调用redis是通过框架提供的yiiredis插件,可能不太符合你的环境,但其中的思路或许还是可以借鉴的。

1、安装Redis

进入终端命令窗口(快捷键Ctrl+Alt+T)切换至/usr/local/src(命令:cd /usr/local/src)下,下载并安装redis:

$ wget http://redis.googlecode.com/files/redis-2.6.12.tar.gz

$ tar xzf redis-2.6.12.tar.gz

$ cd redis-2.6.12

$ make进入redis-2.6.12(命令:

cd redis-2.6.12)目录,修改redis.conf:

daemonize yes启动服务端:

$ src/redis-server redis.conf进入命令行验证服务是否启动:

$ src/redis-cli

redis> set foo bar

OK

redis> get foo

"bar"

2、安装Yii的Redis插件

目前主要有两种Yii插件:

1>  Rediscache:基于predis(Redis的纯PHP实现客户端),无需安装Redis for PHP扩展。

2> YiiRedis:基于phpredis客户端,需要安装Redis for PHP扩展。

这里采用Rediscache插件,避免线上安装Redis for PHP扩展。

从以下地址下载Rediscache插件:

http://www.yiiframework.com/extension/rediscache/files/redis.zip

将插件解压到helloyii/app/protected/extensions中:

插件文件部署后的位置应为:helloyii/app/protected/extensions/redis/CredisCache.php

配置Rediscache

return array(

'components' => array(

'cache'=>array(

'class'=>'ext.redis.CRedisCache', //对应protected/extensions/redis/CredisCache.php

'servers'=>array(

array(

'host'=>'127.0.0.1',

'port'=>6379,

),

),

),

),

);

3、测试redis使用

编写一个读写缓存的控制器IndexController进行测试。

class IndexController extends CController{

public function actionSetRedisValue() {

$key = $_POST['key'];

$value = $_POST['value'];

if ( !empty( $key ) && !empty( $value ) ) {

try {

$redis = Yii::app()->cache;

$data = ( array ) $redis->get( 'test' );

$data[$key] = $value;

$redis->set( 'test', $data );

die( json_encode( array( 'status' => 1, 'msg' => 'set ok!' ) ) );

} catch ( Exception $e ) {

die( json_encode( array( 'status' => 0, 'msg' => 'set faile!' ) ) );

}

} else {

die( json_encode( array( 'status' => 0, 'msg' => 'must input!' ) ) );

}

}

public function actionGetRedisValue() {

try {

$redis = Yii::app()->cache;

$data = ( array ) $redis->get( 'test' );

$log_file = Yii::app()->runtimePath . '\redis_log.txt';

if ( file_exists( $log_file ) ) {

$handle = fopen( $log_file, "a+" );

$log = "----" . date( 'Y-m-d H:i:s' ) . "-----" . "\n";

foreach ( $data as $key => $value ) {

$log .= '->' . $key . ' = ' . $value . "\n";

}

fwrite( $handle, $log );

fclose( $handle );

}

} catch ( Exception $e ) {

echo $e->getMessage();

}

}

}

视图文件index内容。

<?php Yii::app()->clientScript->registerCoreScript( 'jquery' ); ?>

Redis

Key:

Value:

$(document).ready(function() {

$('#redis_form #set').on('click', function() {

var redisForm = $('#redis_form');

var action = redisForm.attr('action');

var key = redisForm.children('#key');

var value = redisForm.children('#val');

$.post(action, {key: key.val(), value: value.val()}, function(data) {

redisForm.find('span').html(data.msg);

setTimeout(function() {

redisForm.find('span').html('');

}, 3000);

}, 'json');

});

$('#redis_form #get').on('click', function() {

$.post('<?php echo $this->createUrl( '/cata/index/getRedisValue' ); ?>', {}, function(data) {

}, 'json');

});

});

现在访问:http://helloyii.com/app/index.php?r=cache/fetch&key=a&value=b

然后通过redis-cli命令行客户端查看下缓存的变化:

可以通过redis-cli客户端查看缓存:

$ src/redis-cli

redis> keys '*'

4、添加crontab命令,每10秒获取redis缓存数据进行处理很多时候,我们计划任务需要精确到秒来执行,但linux最小只支持分钟,很多linux自带的版本都不直接支持以秒来执行,根据以下方法,可以很容易地以秒执行任务。进入终端编辑crontab(命令:crontab -e)

* * * * * /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

* * * * * sleep 10; /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

* * * * * sleep 20; /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

* * * * * sleep 30; /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

* * * * * sleep 40; /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

* * * * * sleep 50; /usr/bin/wget -q http://localhost/suixingv3/index.php/cata/index/getRedisValue

5、调试

当你通过redis往内存中设置多几个值之后,再获取的时候redis可能会报一下的这种错误:

Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

产生时的条件:

数据持续写入,读取速度远低于写入速度,持续1H以上(中途开了一个较长时间的会,一直写入数据,没管),内存占用量为80%。

由于我目前并未对redis做详细深入理解,故根据网上资料说明:

stop-writes-on-bgsave-error yes

默认情况下,如果在RDB snapshots持久化过程中出现问题,设置该参数后,Redis是不允许用户

进行任何更新操作(set...)。避免人为强制停止redis 快照

解决:

进入redis/src目录下启动客户端:

$ ./redis-cli

输入:

config set stop-writes-on-bgsave-error no

6、参考资料

官方安装手册 http://redis.io/download Yii的Redis插件1:rediscache http://www.yiiframework.com/extension/rediscache/ Yii的Redis插件2:yiiredis https://github.com/phpnode/YiiRedis  Yii CCache接口的API http://www.yiichina.com/api/CCache#get-detail  Redis在YiiFramework中的使用 http://denghai260.blog.163.com/blog/static/726864092012323101628773/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值