十七度 “资料设置”里一直有“邮件通知”功能,但是一直没有实现功能,晚上闲来无事,顺手把这个功能做了,记录一下实现过程。
主要是站内通知通过邮件的方式通知用户,比如文章被点赞、有了新粉丝、动态被评论,这些功能不能做成同步的,因为发送邮件比较耗时,所以只能“异步”的实现,RabbitMQ 倒是可以实现,但是太复杂了,还得装软件,所以就使用 Redis 的 push 和 pop 简单的实现了下。
首先在 消息 表入库完成后往 list 里 push 一个 消息ID
Yii::$app->redis->rpush('notification_list', $this->id);
然后新建一个脚本定时的 pop 消息ID 发送邮件即可
$redis = Yii::$app->redis;
// 任务是否正在处理中
$taskRunningFlag = $redis->get('notification_running_flag');
$pendingTaskCount = $redis->llen('notification_list');
if ($taskRunningFlag) {
exit("任务处理中, 上次未处理任务数: " . $pendingTaskCount . "\n");
}
// 标记任务正在处理中
$redis->set('notification_running_flag', 1);
while (($taskCount = $redis->llen('notification_list')) > 0) {
$notificationId = $redis->lpop('notification_list');
// 未找到通知,结束任务
$notification = Notification::findOne($notificationId);
if (empty($notification)) {
$this->stdout("获取通知详情失败, notification_id: {$notificationId} \n");
continue;
}
try {
// 发送邮件,代码就不写了,很简单
} catch (\Exception $e) {
$redis->del('notification_running_flag');
$this->stdout("发送邮件通知失败:{$e->getMessage()}");
Yii::debug("发送邮件通知失败:{$e->getMessage()}");
}
}
// 删除任务正在处理中的标记
$redis->del('notification_running_flag');
exit("任务处理完成, 共处理 {$pendingTaskCount} 条任务\n");
然后新建一个 crontab 任务 每分钟执行一下脚本就行
*/1 * * * * /usr/local/php/bin/php [脚本路径] > /home/crontablogs/notification.log
试了下,没啥大问题,跑的挺happy。
