您的位置:一分快三全天精准计划 > 1分快3全天计划官方网站-编程 > 1、当一个业务触发以后需要启动一个定时任务

1、当一个业务触发以后需要启动一个定时任务

2020-02-29 23:37

简单来讲准时职务应用方案:使用redis的keyspace notifications 需求静心此意义是在redis 2.8版本之后临蓐的,由此你服务器上的reids最少如若2.8本子以上;

1、当叁个职业触发以往供给运营三个依期职分,在指准时间内再去试行一个职分

2、redis的keyspace notifications 会在key失效后发送二个事件,监听那一件事件的的顾客端就足以接收布告

1、修改reids配置文件【window系统配置文件为:redis.windows.conf 】

redis默许不会张开keyspace notifications,因为张开后会对cpu有消耗

备注:E:keyevent事件,事件以__keyevent@__为前缀举行透露;

x:过期事变,当有些键过期并删除时会发生该事件;

notify-keyspace-events ""

notify-keyspace-events "Ex"

保留配置后,重启Redis服务,使配置生效

[root@chokingwin etc]#service redis-server restart /usr/local/redis/etc/redis.conf Stopping redis-server: [ OK ] Starting redis-server: [ OK ]

window系统重启redis ,先切换来redis文件目录,然后关闭redis服务(redis-server --service-stop),再展开(redis-server --service-start)

phpredis完成订阅Keyspace notification,可达成机关撤除订单,自动完毕订单。以下为测量试验例子

开创4个公文,然后自动改革数据库和redis配置参数

db.class.php

'127.0.0.1', 'username'=>'root', 'password'=>'168168', 'database'=>'test', 'port'=>3306, ); $host = $config['host']; //主机地址 $username = $config['username'];//用户名 $password = $config['password'];//密码 $database = $config['database'];//数据库 $port = $config['port']; //端口号 $this->mysqli = new mysqli($host, $username, $password, $database, $port); } /** * 数据查询 * @param $table 数据表 * @param null $field 字段 * @param null $where 条件 * @return mixed 查询结果数目 */ public function select($table, $field = null, $where = null) { $sql = "SELECT * FROM `{$table}`"; //echo $sql;exit; if  { $field = '`' . implode . '`'; $sql = str_replace; } if  { $sql = $sql . ' WHERE ' . $where; } $this->result = $this->mysqli->query; return $this->result; } /** * @return mixed 获取全部结果 */ public function fetchAll() { return $this->result->fetch_all; } /** * 插入数据 * @param $table 数据表 * @param $data 数据数组 * @return mixed 插入ID */ public function insert { foreach ($data as $key => $value) { $data[$key] = $this->mysqli->real_escape_string; } $keys = '`' . implode('`,`', array_keys . '`'; $values = ''' . implode("','", array_values . '''; $sql = "INSERT INTO `{$table}`VALUES"; $this->mysqli->query; return $this->mysqli->insert_id; } /** * 更新数据 * @param $table 数据表 * @param $data 数据数组 * @param $where 过滤条件 * @return mixed 受影响记录 */ public function update($table, $data, $where) { foreach ($data as $key => $value) { $data[$key] = $this->mysqli->real_escape_string; } $sets = array(); foreach ($data as $key => $value) { $kstr = '`' . $key . '`'; $vstr = ''' . $value . '''; array_push($sets, $kstr . '=' . $vstr); } $kav = implode; $sql = "UPDATE `{$table}` SET {$kav} WHERE {$where}"; $this->mysqli->query; return $this->mysqli->affected_rows; } /** * 删除数据 * @param $table 数据表 * @param $where 过滤条件 * @return mixed 受影响记录 */ public function delete { $sql = "DELETE FROM `{$table}` WHERE {$where}"; $this->mysqli->query; return $this->mysqli->affected_rows; }}

$order_sn,'status'=>0,'createtime'=>date]; $mysql->insert;}$list = [$order_sn,$use_mysql];$key = implode;$redis->setex; //3秒后回调$test_del = false; //测试删除缓存后是否会有过期回调。结果:没有回调if{ //sleep; $redis->delete;}echo $order_sn;/* * 测试其他key会不会有回调,结果:有回调 * $k = 'test'; * $redis2->set; * $redis2->expire; **/

psubscribe.php

setOption();//当key过期的时候就看到通知,订阅的key __keyevent@__:expired 这个格式是固定的,db代表的是数据库的编号,由于订阅开启之后这个库的所有key过期时间都会被推送过来,所以最好单独使用一个数据库来进行隔离$redis->psubscribe(array('__keyevent@'.$redis_db.'__:expired'), 'keyCallback');// 回调函数,这里写处理逻辑function keyCallback($redis, $pattern, $channel, $msg){ echo PHP_EOL; echo "Pattern: $patternn"; echo "Channel: $channeln"; echo "Payload: $msgnn"; $list = explode; $order_sn = isset?$list[0]:'0'; $use_mysql = isset?$list[1]:'0'; if{ require_once 'db.class.php'; $mysql = new mysql; $where = "ordersn = '".$order_sn."'"; $mysql->select; $finds=$mysql->fetchAll; if(isset && $finds[0]['status']==0){ $data = array; $where = " id = ".$finds[0]['id']; $mysql->update; } }}//或者/*$redis->psubscribe(array('__keyevent@'.$redis_db.'__:expired'), function ($redis, $pattern, $channel, $msg){ echo PHP_EOL; echo "Pattern: $patternn"; echo "Channel: $channeln"; echo "Payload: $msgnn"; //................});*/

Redis2.class.php

redis = new Redis(); $this->redis->connect; //连接Redis $this->redis->auth; //密码验证 $this->redis->select; //选择数据库 } public function setex { return $this->redis->setex; } public function set { return $this->redis->set; } public function get { return $this->redis->get; } public function expire($key = null, $time = 0) { return $this->redis->expire; } public function psubscribe, $callback) { $this->redis->psubscribe; } public function setOption() { $this->redis->setOption(Redis::OPT_READ_TIMEOUT, -1); } public function lRange { return $this->redis->lRange; } public function lPush($key, $value1, $value2 = null, $valueN = null ){ return $this->redis->lPush($key, $value1, $value2 = null, $valueN = null ); } public function delete($key1, $key2 = null, $key3 = null) { return $this->redis->delete($key1, $key2 = null, $key3 = null); }}

window系统一测验试方法:先在cmd命令分界面运营psubscribe.php,然后网页展开index.php。

使监听后台一贯运作

有个难点 做到这一步,利用 phpredis 扩大,成功在代码里金玉锦绣对逾期 Key 的监听,并在 psCallback(卡塔尔(قطر‎里展开回调解和管理理。起头建议的四个必要已经落到实处。然而这里有个难点:redis 在实行完订阅操作后,终端步向窒碍状态,须求一贯挂在那。且此订阅脚本须要人工在命令行施行,不切实际要求。

实在,大家对过期监听回调的急需,是期望它像守护进度相近,在后台运维,当有逾期事件的消息时,触发回调函数。使监听后台平素运作 希望像守护进度同样在后台相符,

Linux中有一个nohup命令。效用就是不挂断地运转命令。同期nohup把剧本程序的持有出口,都放置当前目录的nohup.out文件中,假如文件不可写,则停放/nohup.out 文件中。那么有了这一个命令未来,不管大家终端窗口是还是不是关闭,都可以让我们的php脚本一贯运行。

编写psubscribe.php文件:

setOption();//当key过期的时候就看到通知,订阅的key __keyevent@__:expired 这个格式是固定的,db代表的是数据库的编号,由于订阅开启之后这个库的所有key过期时间都会被推送过来,所以最好单独使用一个数据库来进行隔离$redis->psubscribe(array('__keyevent@'.$redis_db.'__:expired'), 'keyCallback');// 回调函数,这里写处理逻辑function keyCallback($redis, $pattern, $channel, $msg){ echo PHP_EOL; echo "Pattern: $patternn"; echo "Channel: $channeln"; echo "Payload: $msgnn"; $list = explode; $order_sn = isset?$list[0]:'0'; $use_mysql = isset?$list[1]:'0'; if{ require_once 'db.class.php'; $mysql = new mysql; $where = "ordersn = '".$order_sn."'"; $mysql->select; $finds=$mysql->fetchAll; if(isset && $finds[0]['status']==0){ $data = array; $where = " id = ".$finds[0]['id']; $mysql->update; } }}//或者/*$redis->psubscribe(array('__keyevent@'.$redis_db.'__:expired'), function ($redis, $pattern, $channel, $msg){ echo PHP_EOL; echo "Pattern: $patternn"; echo "Channel: $channeln"; echo "Payload: $msgnn"; //................});*/

注意:我们在起头,声明 php 编译器的路线:

#! /usr/bin/env php

那是实践 php 脚本所不可不的。

接下来,nohup 不挂起执行 psubscribe.php,注意 末尾的 &

[root@chokingwin HiGirl]# nohup ./psubscribe.php & [1] 4456 nohup: ignoring input and appending output to `nohup.out'

证实:脚本确实已经在 4456 号经过上跑起来。

查看下nohup.out cat 一下 nohuo.out,看下是或不是有逾期输出:

[root@chokingwin HiGirl]# cat nohup.out Pattern:__keyevent@0__:expired Channel: __keyevent@0__:expired Payload: name

运作index.php ,3秒后效果如上即中标

遇见难题:使用命令行方式开启监察和控制脚本 ,一段时间后报错 :Error while sending QUE纳瓦拉Y packet. PID=xxx

化解方法:由于等候信息队列是三个长连接,而等待回调前有个数据库连接,数据库的wait_timeout=28800,所以一旦下一条音信离上一条消息超过8钟头,就能够冒出这一个错误,把wait_timeout设置成10,何况捕获格外,开掘实际的报错是 MySQL server has gone away ,所以借使管理完不论什么事务逻辑后积极关闭数据库连接,即数据库连接主动close掉就足以解决难题

Yii::$app->db->close();

 ps -aux|grep psubscribe.phpa:显示所有程序u:以用户为主的格式来显示x:显示所有程序,不以终端机来区分

查看jobs进程ID:[ jobs -l ]命令

www@iZ232eoxo41Z:~/tinywan $ jobs -l[1]- 1365 Stopped  sudo nohup psubscribe.php > /dev/null 2>&1 [2]+ 1370 Stopped  sudo nohup psubscribe.php > /dev/null 2>&1

停下后台运转的进程方法:

kill -9 进程号

清空 nohup.out文件方法:

cat /dev/null > nohup.out

大家在应用nohup的时候,常常都和&协作使用,可是在其实应用进度中,很两个人后台挂上前后相继就好像此无论了,其实那样有望在时下账户非寻常退出可能终止的时候,命令照旧要好得了了。

进而在利用nohup命令后台运营命令之后,我们供给做以下操作:

1.先回车,退出nohup的提示。

2.然后实行exit平常退出当前账户。3.然后再去链接终端。使得程序后台平常运作。

咱俩应当每一趟都使用exit退出,而不该每便在nohup实行成功后一向关门终端。那样技能作保命令直接在后台运营。

总结

上述所述是作者给我们介绍的运用PHP+Redis达成延迟职分,实现活动撤废订单作用,希望对大家有着帮忙,如果大家有别的疑问请给自己留言,小编会及时苏醒大家的。在这里也极其谢谢大家对台本之家网址的接济!如若你以为本文对您有援救,接待转载,烦请表明出处,感激!

本文由一分快三全天精准计划发布于1分快3全天计划官方网站-编程,转载请注明出处:1、当一个业务触发以后需要启动一个定时任务

关键词: