异曲同工的租约

简介:

问题描述

有这样一个需求:WordPress中有一个叫做wp-cron.php的文件,它负责做一些定时任务,例如定时发送博文,定时清理垃圾回复等。因为WordPress是运行在Web PHP环境下,不借助第三方工具,实现定时任务有一定的困难。它的思路是,每当博客有点击时,就总触发一次cron,为了不阻塞客户的正常访问,用到了fopensocket 发起一个异步cron请求,当cron页面收到这个请求的时候,就开始检查各种执行条件,如果条件满足,则从数据库中获取cron任务并执行。

这里的问题是,如果有两个用户同时点击了页面,同时触发了cron任务,如何保证只起一个cron?如何保证起了一个cron后,它不会退出,常驻后台?如何保证万一cron退出了,会有后备的cron能起来?

基本流程


对于每一个cron请求,按照下面的顺序执行: 
SELECT获取一个任务 
把这个任务从数据表中删除 
检查删除是否成功 
-如果删除成功,则开始执行SELECT到的任务 
-否则直接退出(有另外一个cron请求也在执行这个任务)

存在的问题


这种方法简单粗暴,很能解决问题,但是它有这样几个问题:

-顺序问题:SELECT取任务的顺序必须都一致。cron1取A、B;cron2取B、A,则可能两个cron都会先后主动退出,导致后台没有cron了。 
-开销问题:每次都会尝试起cron,意味着每次都会发起一次内部的http连接

如何解决


  1. 顺序问题:这个保证每次SELECT都是按照主键顺序取即可,或者按照某个行值唯一的列顺序执行即可。
  2. 开销问题:引入lease(租约)机制,每个cron job一旦启动,就会持有一个lease(3秒),每次执行完一个任务,就续一下自己的lease。任何cron希望启动的时候,必须先看一下lease是否过期,如果lease过期,则立即获取lease,并启动自己。
  3. 由于没有加锁,可能两个cron都抢到了lease,没关系,当他们处理任务的时候,会有一个主动放弃(见上面的流程说明)。这种情况比较罕见,不会影响性能。

缺陷


上面的方案,在特殊情况下还是有一些小缺陷: 
1. cron job中途异常退出后的3秒内,新的任务无法被执行。如果cron job异常退出3秒后,不再有新的请求到来,那么任务队列中堆积的任务将无人处理。

如果cron job异常退出的可能性比较低,则这不是一个很大的问题。如果需要确保任务总能被及时执行,可以考虑使用Linux系统自带的crontab,来定时触发PHP的Cron Job。

关于LEASE


分布式系统中,Lease的概念被广泛采用。当我们无法确切了解到彼此的行为时,我们可以依赖一套约定,来规范和预测彼此的行为,以保障系统处于一个一致的状态。所谓“一致的状态”,就是我们觉得正确、可以理解的状态。上文中,两个cron请求无法知道彼此的存在,通过Lease的方式,很好地达成了一致,不会出现两个cron job同时运行的窘境。

补记


PHP脚本的执行时间,是有限制的,即使在脚本执行之初调用了 ignore_user_abort 方法。该方法的语义是设置客户端断开连接时是否中断脚本的执行,并不能改变PHP脚本最长。控制PHP最大执行时长的,需要修改php-fpm、nginx等的配置,详细参考 这里这里 。不过,在脚本中,也是可以改变PHP的最大执行时间的,相关函数请参考set_time_limit()ini_set(“max_execution_time”, “45”),这里还有一篇小结。根据PHP官方文档,希望在脚本中设定最大执行时间的时候,必须保证php.ini配置中safe_mode=Off。一般默认改选项都是Off,所以你可以在脚本中设置一个无限长的脚本运行时间。不过,安全起见,不建议运行无限长的时间,而是应该在ini_get(“max_execution_time”)的基础上减去若干秒来运行,然后主动释放lease。

目录
相关文章
|
18天前
|
Linux 网络架构 Windows
TTL传输中过期原因,ttl传输中过期的解决办法(ttl传输中过期怎么解决)
A3: 实际上,TTL值需依据实际网络环境设定。过小的TTL值可能导致数据包过早丢弃,影响通信;反之,过大的TTL值则可能占用不必要的网络资源。因此,科学合理的TTL值设定是平衡通信效率与资源利用的关键。
231 0
配置的代理服务器未响应怎么办
配置的代理服务器未响应怎么办
|
6月前
|
域名解析 网络协议 数据库
dns问题之服务器未响应如何解决
DNS服务器是负责将域名转换为IP地址的服务,它是互联网上实现域名解析的关键基础设施;本合集将探讨DNS服务器的工作原理、配置方法和常见问题处理,帮助用户理解和优化DNS服务的使用。
192 10
|
弹性计算 运维 Kubernetes
为什么客户端发送SYN,服务端回ACK,没有回SYN,ACK
本文介绍了客户端发生SYN报文但是服务端回复ACK报文没有回复SYN,ACK报文的场景,深入分析了内核代码处理机制以及使用复现验证
2388 1
|
缓存 网络协议 算法
|
存储 Kubernetes API
关于k8s 集群中证书期限及续约的一些笔记
嗯,k8s 集群CA 证书突然过期了,所有这里整理相关笔记 博文内容涉及: 如何确认证书是否过期 通过 kubeadm 批量续约证书 Demo 理解不足小伙伴帮忙指正
370 0
|
存储 NoSQL
3.10.0-693.5.2内核nfs客户端租约过期挂死问题分析
## 现象 1. 边缘存储两个节点fileserver,glance挂载物理机上的挂载点均出现挂住无法访问 2. 从客户端抓包看,客户端内核间隔5s向服务端发送renew租约请求,服务端返回NFS4ERR_EXPIRED,即租约过期错误,从抓包现象看客户端一直向服务端发送相同的clientid renew请求,服务端一直返回租约过期错误,导致挂载点无法恢复 ![](https://ata2-img
1642 1
3.10.0-693.5.2内核nfs客户端租约过期挂死问题分析
|
应用服务中间件 nginx 网络协议
lvs为何不能完全替代DNS轮询
“DNS轮询”究竟是不是过时的技术,是不是可以被其他方案替代,接入层架构技术演进,是本文将要细致讨论的内容。
5231 0