【问题标题】:How to implement semaphores in PHP without PHP Semaphore?如何在没有 PHP Semaphore 的情况下在 PHP 中实现信号量?
【发布时间】:2011-03-07 23:23:33
【问题描述】:

问题:

如何在没有信号量包的情况下在 PHP 中实现共享内存变量 (http://php.net/manual/en/function.shm-get-var.php)?

上下文

  • 我有一个简单的 Web 应用程序(实际上是 WordPress 的插件)
  • 这会得到一个网址
  • 然后检查数据库是否该 url 已经存在
  • 如果不是,则它会退出并执行一些操作
  • 然后将记录写入数据库中,以url作为唯一条目

实际发生的情况是 4,5,6 ... 会话同时请求 url,我在 url 的数据库中获得多达 9 个重复条目..(可能是 9,因为处理时间和数据库写入第一个条目只需要足够的时间让其他 9 个请求通过)。之后,所有请求都读取记录已经存在的正确条目,这很好。

由于它是一个 WordPress 插件,因此在各种共享主机平台上都会有很多用户使用可变的 PHP 编译/设置。

所以我正在寻找更通用的解决方案。我不能使用数据库或文本文件写入,因为它们太慢了。当我写到数据库时,下一个会话已经过去了。

仅供参考:数据库代码:http://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/plugins/metadata_favicon/inc/class-favicon.php

更新

在 uri 的新 md5 散列上使用唯一键以及周围的 try catch 似乎有效。

我发现 1 个重复条目与

SELECT uri, COUNT( uri ) AS NumOccurrences
FROM edl40_21_wpfavicons_1
GROUP BY uri
HAVING (
COUNT( uri ) >1
)
LIMIT 0 , 30

所以我认为它不起作用,但这是因为它们是:

http://en.wikipedia.org/wiki/Book_of_the_dead
http://en.wikipedia.org/wiki/Book_of_the_Dead

(大写的咧嘴笑)

【问题讨论】:

    标签: php wordpress locking deadlock semaphore


    【解决方案1】:

    这可以通过 MySQL 来实现。

    您可以通过锁定表的读取访问权限来显式执行此操作。不过,这将阻止对整个表的任何读取访问,因此可能不是可取的。 http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html

    否则,如果表中的字段被归类为唯一字段,那么当下一个会话尝试将相同的 URL 写入表时,他们将收到错误,您可以捕获该错误并继续,因为如果出现以下情况则无需执行任何操作条目已经存在。唯一浪费的时间是两个或多个会话创建相同 URL 的可能性,结果仍然是一条记录,因为数据库不会再次添加相同的唯一 URL。

    正如在 cmets 中所讨论的,因为 URL 的长度可能很长,而固定长度的唯一哈希可以帮助解决这个问题。

    【讨论】:

    • 这是一个很大的额外存储空间,但也许您可以使用唯一的散列代替?
    • 锁定整个表有点苛刻,在 1 次锁定期间,我可能有大约 N 个进程无法写入(来自不同的 uri)。 In can not make uri unique:唯一字段有最大长度。独特的哈希很有趣,也许这就是美味的作用。在这里你可以看到混合的数据库请求:leau.co/wp-content/blogs.dir/21/files/wp-favicons/cache/…
    • 因为我不知道是否存在 uri 记录,它可能会像这样 (A) 更新 LOCK 记录 where uri_hash=md5(uri) try catch (B) 如果存在则读取 (C) if它存在版本 A (D) 如果不存在,则处理、编写和发布 A - 让我试试 :)
    • 是的,锁定将阻止任何进一步的请求。我会尝试独特的哈希方法,让 MySQL 防止添加重复项。有趣的问题。
    • stackoverflow.com/questions/5109825/… 的问题是在读取过程中结果是记录不存在。如果它不存在,则没有什么可锁定的,N 个会话开始处理所有想要写入的内容,但这可以通过设置哈希唯一来解决。但我仍然有 n 个进程在运行。可能我可以通过始终尝试使用 try catch 尝试插入来防止这种情况发生。并在 catch 中处理 php 逻辑并设置一个布尔值......必须通过大声笑。
    【解决方案2】:

    PHP 中还有其他共享内存模块(例如shmopAPC),但我认为您的意思是依赖非标准/未预安装的库存在问题。

    我的建议是,在您进行“其他操作”之前,您需要在数据库中创建一个条目,可能状态为“正在编译”(或其他),这样您就知道它仍然不可用。这样您就不会遇到获取多个条目的问题。我还可以确保您在事务可用时使用它们,因此您的提交是原子的。

    然后,当您完成“其他操作”后,将数据库条目更新为“可用”,然后执行您需要执行的任何其他操作。

    【讨论】:

      猜你喜欢
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      相关资源
      最近更新 更多