【问题标题】:WordPress Write Cache Issue with Multiple Sessions多个会话的 WordPress 写入缓存问题
【发布时间】:2023-03-28 06:13:01
【问题描述】:

我正在开发 WordPress 中的内容滴灌自定义插件,我的客户要求我构建该插件。他说他希望它捕捉页面浏览事件,并且如果它是一天中的正确时间(自上次发布后 24 小时),从资源文件中提取并输出另一个帖子。他还需要它来提高标志并防止其他会话触发相同的 sn-p 代码。所以,举起某种标志说,“我正在发布那个帖子,离开其他进程”,然后它发布那个帖子并再次发布标志。

然而,最奇怪的事情发生在负载下,多个会话通过页面浏览量访问网站。它正在解雇而不是发布一个帖子——它随机发布了 1、2 或 3 个额外的帖子,每个人都认为这是发布的正确时间,因为它比上一个帖子的时间晚了 24 小时。因为它有点随机,我猜问题是某种写入缓存,其他会话直到几微秒过去后才看到引发的标志。

插件通过简单地使用 WordPress 中的 update_option() API 写入 wp_options 表来提高“标志”。其他用户会话应该使用 get_option() 读取该值并查看标志,然后不运行创建帖子的那段代码,因为给定的会话已经在执行它。然后,完成后,我降低标志,其他会话继续正常进行。

但它正在做的是让其他会话进入。

为了完成这项工作,我使用了 add_action('loop_start','checkToAddContent')。不过,该函数的奇怪之处在于它在一个页面上被多次调用,实际上某些插件可能会调用它。我不知道是否有更好的事件可以挂钩。即便如此,即使我发现一个仅在页面视图上运行一次的要挂钩的事件,我仍然有多个会话要处理(可能同时查看页面的不同用户)并且我希望只触发一个给定的会话当帖子按计划到期时发布的内容。

我想知道是否有任何 WordPress 插件开发人员可以建议使用另一个事件挂钩,并找出另一种方法来引发所有会话都会看到的标志。我的意思是,我可以在 PHP 中使用共享内存 API,但是许多托管计划都禁用了它。不能使用 cookie 或会话变量,因为那只是一个会话。唯一可能跨托管计划起作用的是将文件作为标志删除。如果该文件存在,则一个会话具有该标志。如果该文件不存在,则其他会话可以尝试获取该标志。当然,我可以使用文件路由,但在我看来它有点不成熟,我想知道在 WordPress 中是否有什么我可以做的。

【问题讨论】:

  • 类似 Twitter 的版本:有什么方法可以在所有会话都看到的 wordpress 中升旗? update_option() 有延迟。其他会话没有及时看到它。
  • 走得更远了。有人建议避免使用“loop_start”并使用“wp”事件。然后,在该事件中,在 if( is_single() || is_page() || is_home() || is_archive() || is_category() || is_tag()) { //add code here } 中运行代码。仍然不能解决标志问题,但它是一个更好的使用事件,因为它每次页面视图只运行一次。

标签: wordpress session caching


【解决方案1】:

关键可能是在数据库中为“滴水”事件创建一个信号量记录。

警告 - 考虑以下伪代码 - 我不是在查找函数。

查询帖子时,使用类似的SQL语句

$ts = get_time_now(); // or whatever the function is
$sid = session_id();

INSERT INTO table (postcategory, timestamp, sessionid)
VALUES ("$category", $ts, "$sid")
WHERE NOT EXISTS (SELECT 1 FROM table WHERE postcategory = "$category"
    AND timestamp < $ts - 24 hours)

数据库完整性将使这个原子化,因此只能插入一条记录。 并且只有在超过时间跨度时才会进行插入。

然后立即检查当前的 session_id() 和时间戳是否是你的。如果是,请滴水。

从表中选择 sessionid WHERE postcategory = "$postcategory" AND 时间戳 = $ts AND sessionid = "$sid"

【讨论】:

    【解决方案2】:

    即使来自同一会话(同一访问者)的页面请求也会出现此问题,但来自不同访问者的页面请求也会出现此问题。它的工作原理是这样的:

    • 如果你正在做内容滴漏,那么页面请求可能就是你使用 add_action('wp','myPageRequest') 拦截的内容。从那里,如果预定的帖子到期,那么您创建新帖子。

    • 帖子需要一点时间才能写入数据库。在那个时候,对 get_posts() 的查询可能还看不到新记录。它实际上可能会触发您的一段代码在已经放置一个新帖子时创建一个新帖子。

    解决方法是强制 WordPress 刷新写入缓存,看起来是这样的:

    try {
      $asPosts = array();
      $asPosts = @ wp_get_recent_posts(1);
      foreach($asPosts as $asPost) {break;}
      @ delete_post_meta($asPost['ID'], '_thwart');
      @ add_post_meta($asPost['ID'], '_thwart', '' . date('Y-m-d H:i:s'));
    } catch (Exception $e) {}
    $asPosts = array();
    $asPosts = @ wp_get_recent_posts(1);
    foreach($asPosts as $asPost) {break;}   
    $sLastPostDate = '';
    @ $sLastPostDate = $asPost['post_date'];
    $sLastPostDate = substr($sLastPostDate, 0, strpos($sLastPostDate, ' '));
    $sNow = date('Y-m-d H:i:s');
    $sNow = substr($sNow, 0, strpos($sNow, ' '));
    if ($sLastPostDate != $sNow) {
      // No post today, so go ahead and post your new blog post.
      // Place that code here.
    }
    

    我们要做的第一件事是获取最新的帖子。但我们并不在乎它是否不是最新的帖子。我们得到它只是为了获得一个 Post ID,然后我们添加一个隐藏的自定义字段(因此它以下划线开头)称为

    _thwart

    ...例如,通过将一些数据发布到 CPU 不太重的数据库来阻止写入缓存。

    一旦到位,我们还会再次使用 wp_get_recent_posts(1) 以便我们可以查看最新的帖子是否不是今天的日期。如果没有,那么我们很清楚可以滴入一些内容。(或者,如果您只想像每 72 小时等一样滴入,您可以在此处稍作更改。)

    【讨论】:

      猜你喜欢
      • 2012-06-12
      • 2015-06-22
      • 2019-06-04
      • 2015-04-26
      • 2016-01-28
      • 2013-06-22
      • 1970-01-01
      • 2017-03-24
      • 2016-07-04
      相关资源
      最近更新 更多