简单定时任务解决方案:使用redis的keyspace notifications(键失效后通知事件) 须要注意此功能是在redis 2.8版本之后推出的,所以你服务器上的reids最少要是2.8版本以上;javascript
(A)业务场景:php
一、当一个业务触发之后须要启动一个定时任务,在指定时间内再去执行一个任务(如自动取消订单,自动完成订单等功能)java
二、redis的keyspace notifications 会在key失效后发送一个事件,监听此事件的的客户端就能够收到通知mysql
(B)服务准备:nginx
一、修改reids配置文件(redis.conf)【window系统配置文件为:redis.windows.conf 】redis
redis默认不会开启keyspace notifications,由于开启后会对cpu有消耗sql
备注:E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布;shell
x:过时事件,当某个键过时并删除时会产生该事件;数据库
原配置为:windows
更改 配置以下:
保存配置后,重启Redis服务,使配置生效
window系统重启redis ,先切换到redis文件目录,而后关闭redis服务(redis-server --service-stop),再开启(redis-server --service-start)
C)文件代码:
phpredis实现订阅Keyspace notification,可实现自动取消订单,自动完成订单。如下为测试例子
建立4个文件,而后自行修改数据库和redis配置参数
db.class.php
index.php
psubscribe.php
Redis2.class.php
window系统测试方法:先在cmd命令界面运行psubscribe.php,而后网页打开index.php。
有个问题 作到这一步,利用 phpredis 扩展,成功在代码里实现对过时 Key 的监听,并在 psCallback()里进行回调处理。开头提出的两个需求已经实现。但是这里有个问题:redis 在执行完订阅操做后,终端进入阻塞状态,须要一直挂在那。且此订阅脚本须要人为在命令行执行,不符合实际需求。
实际上,咱们对过时监听回调的需求,是但愿它像守护进程同样,在后台运行,当有过时事件的消息时,触发回调函数。使监听后台始终运行 但愿像守护进程同样在后台同样,
我是这样实现的。
Linux中有一个nohup命令。功能就是不挂断地运行命令。同时nohup把脚本程序的全部输出,都放到当前目录的nohup.out文件中,若是文件不可写,则放到<用户主目录>/nohup.out 文件中。那么有了这个命令之后,无论咱们终端窗口是否关闭,都可以让咱们的php脚本一直运行。
编写psubscribe.php文件:
注意:咱们在开头,申明 php 编译器的路径:
这是执行 php 脚本所必须的。
而后,nohup 不挂起执行 psubscribe.php,注意 末尾的 &
说明:脚本确实已经在 4456 号进程上跑起来。
查看下nohup.out cat 一下 nohuo.out,看下是否有过时输出:
运行index.php ,3秒后效果如上即成功
遇到问题:使用命令行模式开启监控脚本 ,一段时间后报错 :Error while sending QUERY packet. PID=xxx
解决方法:因为等待消息队列是一个长链接,而等待回调前有个数据库链接,数据库的wait_timeout=28800,因此只要下一条消息离上一条消息超过8小时,就会出现这个错误,把wait_timeout设置成10,而且捕获异常,发现真实的报错是 MySQL server has gone away ,
因此只要处理完全部业务逻辑后主动关闭数据库链接,即数据库链接主动close掉就能够解决问题
yii解决方法以下:
查看进程方法:
查看jobs进程ID:[ jobs -l ]命令
终止后台运行的进程方法:
清空 nohup.out文件方法:
咱们在使用nohup的时候,通常都和&配合使用,可是在实际使用过程当中,不少人后台挂上程序就这样无论了,其实这样有可能在当前帐户非正常退出或者结束的时候,命令仍是本身结束了。
因此在使用nohup命令后台运行命令以后,咱们须要作如下操做:
1.先回车,退出nohup的提示。
2.而后执行exit正常退出当前帐户。3.而后再去连接终端。使得程序后台正常运行。