我想在对虚拟命名资源的 PHP 请求之间实现一种快速有效的序列化机制,当脚本完成时,无论是正常还是由于错误,它都会解锁。我过去有 eaccelerator_lock() 及其对应的 eaccelerator_unlock() ,但 eaccelerator 不再实现该功能。我想做的是:
lock_function("my-named-resource");
..
my_might_abort_abruptly_function();
..
unlock_function("my-named-resource");
其他使用完全相同参数调用 lock_function() 的 PHP 脚本应该阻塞,直到该脚本调用 unlock_function() 或中止。资源名称在处理之前是未知的(它是一个生成的字符串),并且不能被限制在一个小集合中(即锁定机制应该具有良好的粒度)。我想避免使用 try/catch 代码,因为在某些情况下不调用 catch。此外,应避免任何依赖于手动 usleep() 旋转(而不是本机操作系统阻塞)的机制。
我的是服务器中唯一正在运行的应用程序。该系统是带有 PHP 5.3.3、Apache 2.2.15 的 CentOS 6 Linux,我可以完全控制它。
我探索了以下替代方案:
信号量:它们在 PHP 中没有很好地实现;Linux 允许数千个数组,而 PHP 只为每个 id 分配一个。
flock():我的资源是虚拟的,flock() 只会锁定整个/真实/现有文件;我需要预先创建数千个文件并选择一个用哈希函数锁定。粒度取决于文件的数量。
dio_fcntl():我可以尝试用单个文件和 fcntl(F_SETLK) 重现flock() 的想法。这将具有良好粒度而不需要许多文件的优点;该文件甚至可以是零字节长!(F_SETLK 可以锁定超出文件末尾)。唉! 问题是文档中没有任何地方说 dio_fcntl() 将在脚本终止时释放资源。
数据库锁:我可以在具有良好键锁定粒度的数据库中实现一些键锁定,尽管这太依赖于数据库。也不会那么快。
实现我自己的 PHP 扩展:我真的很想避免这条路。
问题是,我认为某个地方的某个人应该在我之前想到这一点。什么是好的选择?还有其他我没有看到的解决方案吗?
提前致谢。吉列尔莫。