2

我试图在 php 中为高流量 wp 站点实现缓存。到目前为止,我设法将结果存储到 ramfs 并直接从 htaccess 加载它们。但是,在高峰时段,生成某个页面的进程不止一个,并且正在成为一个问题

我在想互斥锁会有所帮助,我想知道是否有比 system("mkdir cache.mutex") 更好的方法

4

2 回答 2

1

据我了解,您希望确保一次只有一个进程在运行某段代码。可以为此使用互斥锁或类似机制。我自己使用 lockfiles 来获得一个适用于许多平台的解决方案,并且不依赖于仅在 Linux 等上可用的特定库。

为此,我写了一个Lock小班。请注意,它使用了我的库中的一些非标准函数,例如,获取临时文件的存储位置等。但您可以轻松更改它。

<?php   
    class Lock
    {
        private $_owned             = false;

        private $_name              = null;
        private $_lockFile          = null;
        private $_lockFilePointer   = null;

        public function __construct($name)
        {
            $this->_name = $name;
            $this->_lockFile = PluginManager::getInstance()->getCorePlugin()->getTempDir('locks') . $name . '-' . sha1($name . PluginManager::getInstance()->getCorePlugin()->getPreference('EncryptionKey')->getValue()).'.lock';
        }

        public function __destruct()
        {
            $this->release();
        }

        /**
         * Acquires a lock
         *
         * Returns true on success and false on failure.
         * Could be told to wait (block) and if so for a max amount of seconds or return false right away.
         *
         * @param bool $wait
         * @param null $maxWaitTime
         * @return bool
         * @throws \Exception
         */
        public function acquire($wait = false, $maxWaitTime = null) {
            $this->_lockFilePointer = fopen($this->_lockFile, 'c');
            if(!$this->_lockFilePointer) {
                throw new \RuntimeException(__('Unable to create lock file', 'dliCore'));
            }

            if($wait && $maxWaitTime === null) {
                $flags = LOCK_EX;
            }
            else {
                $flags = LOCK_EX | LOCK_NB;
            }

            $startTime = time();

            while(1) {
                if (flock($this->_lockFilePointer, $flags)) {
                    $this->_owned = true;
                    return true;
                } else {
                    if($maxWaitTime === null || time() - $startTime > $maxWaitTime) {
                        fclose($this->_lockFilePointer);
                        return false;
                    }
                    sleep(1);
                }
            }
        }

        /**
         * Releases the lock
         */
        public function release()
        {
            if($this->_owned) {
                @flock($this->_lockFilePointer, LOCK_UN);
                @fclose($this->_lockFilePointer);
                @unlink($this->_lockFile);
                $this->_owned = false;
            }
        }
    }

用法

现在您可以让两个进程同时运行并执行相同的脚本

过程 1

$lock = new Lock('runExpensiveFunction');

if($lock->acquire()) {
  // Some expensive function that should only run one at a time
  runExpensiveFunction();
  $lock->release();
}

过程 2

$lock = new Lock('runExpensiveFunction');

// Check will be false since the lock will already be held by someone else so the function is skipped
if($lock->acquire()) {
  // Some expensive function that should only run one at a time
  runExpensiveFunction();
  $lock->release();
}

另一种选择是让第二个进程等待第一个进程完成而不是跳过代码。

$lock = new Lock('runExpensiveFunction');

// Process will now wait for the lock to become available. A max wait time can be set if needed.
if($lock->acquire(true)) {
  // Some expensive function that should only run one at a time
  runExpensiveFunction();
  $lock->release();
}

内存盘

要使用锁定文件限制对 HDD/SSD 的写入次数,您可以创建一个 RAM 磁盘来存储它们。

在 Linux 上,您可以添加如下内容/etc/fstab

tmpfs       /mnt/ramdisk tmpfs   nodev,nosuid,noexec,nodiratime,size=1024M   0 0

在 Windows 上,您可以下载ImDisk Toolkit 之类的东西并用它创建一个 ramdisk。

ImDisk RamDisk 配置工具

于 2018-08-16T11:20:08.137 回答
0

我同意@gries 的观点,反向代理将是从大容量 Wordpress 网站中获得高性能的一种非常好的物有所值的方式。我利用 Varnish 取得了相当大的成功,尽管我怀疑你也可以使用 nginx 来做到这一点。

于 2013-06-19T20:08:19.887 回答