Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
自动发布PHP虚拟资源访问序列化_Php_Locking - Fatal编程技术网

自动发布PHP虚拟资源访问序列化

自动发布PHP虚拟资源访问序列化,php,locking,Php,Locking,我想在PHP对虚拟命名资源的请求之间实现一种快速高效的序列化机制,该机制将在脚本完成时解锁(正常情况下或由于错误)。我以前有eaccelerator_lock()及其对应的eaccelerator_unlock(),但eaccelerator不再实现该函数。我想做的是: lock_function("my-named-resource"); .. my_might_abort_abruptly_function(); .. unlock_function("my-named-resource")

我想在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()旋转(而不是本机操作系统阻塞)的机制

Mine是服务器中唯一正在运行的应用程序。该系统是一个CentOS 6 Linux,带有PHP5.3.3、Apache 2.2.15,我完全可以控制它

我探讨了以下备选方案:

  • 信号量:它们在PHP中没有很好地实现;Linux允许数千个数组,而PHP只为每个id分配一个

  • flock():我的资源是虚拟的,flock()只会锁定整个/真实/现有文件;我需要预先创建数千个文件,然后选择一个用哈希函数锁定。粒度将取决于文件的数量

  • dio_fcntl():我可以尝试用一个文件和fcntl(F_SETLK)重现flock()的想法。这将具有良好的粒度优势,而不需要许多文件;该文件甚至可以是零字节长!(F_SETLK可以锁定文件末尾以外的位置)。唉!问题是,文档中没有任何地方说,当脚本终止时,dio_fcntl()将释放资源

  • 数据库锁定:我可以在具有良好密钥锁定粒度的数据库中实现一些密钥锁定,尽管这太依赖于数据库。也不会那么快

  • 实现我自己的PHP扩展:我真的希望避免这种路径

问题是,我想应该有人在我之前想到这一点。什么是好的选择?还有别的解决办法我看不到吗


提前谢谢。Guillermo。

您可以在脚本启动时使用旧的方式创建一个文件,并在脚本完成后将其删除

您可以选择删除该文件

文件的存在或不存在将指示资源的锁定状态

事实证明,dio_open()确实会在脚本终止时释放资源。因此,我最终编写了以下函数:

$lockfile = $writable_dir."/serialized.lock";

function serialize_access($name)
{
    $f = serialize_openfile();
    if( !$f ) return false;
    $h = serialize_gethash($name);
    return dio_fcntl($f, F_SETLKW, array("whence"=>SEEK_SET,"start"=>$h, "length"=>1, "type"=>F_WRLCK)) >= 0;
}

function serialize_release($name)
{
    $f = serialize_openfile();
    if( !$f ) return false;
    $h = serialize_gethash($name);
    @dio_fcntl($f, F_SETLK, array("whence"=>SEEK_SET,"start"=>$h, "length"=>1, "type"=>F_UNLCK));
}

function serialize_gethash($name)
{
    // Very good granularity (2^31)
    return crc32($name) & 0x7fffffff;
}

function serialize_openfile()
{
    global $lockfile, $serialize_file;

    if( !isset($serialize_file) )
    {
        $serialize_file = false;

        if( extension_loaded("dio") )
        {
            $serialize_file = @dio_open($lockfile,O_RDWR);
            if( $serialize_file )
            {
                // Do not attempt to create the file with dio_open()
                // because the file permissions get all mangled.

                $prev = umask(0);
                $temp = fopen($lockfile,"a");
                if( $temp )
                {
                    $serialize_file = @dio_open($lockfile,O_RDWR);
                    fclose($temp);
                }
                umask($prev);
            }
        }
    }

    return $serialize_file;
}
它似乎工作得很好

实现我自己的PHP扩展


您可能需要检查库,它完全符合您的要求

Mmm。。。这是极不可靠的。我知道它已经被广泛使用,但这种方法可能会导致太多问题。确定哪个进程实际生成了锁是非常棘手的。另外,当两个进程试图访问资源时,它不会自动阻塞,因此它会迫使我使用usleep()旋转,等待文件被释放;锁定顺序基于机会,而不是先进先出。使用带有E_EXCL标志的dio_open()可以确保哪个进程是锁的真正创建者,但这只是一个小小的改进。首先,您不需要为flock()预创建文件,您可以动态创建它们。其次,我不知道如何使用
dio\u fcntl()
在一个文件上锁定多个资源?