2011-03-07 42 views
2

问:如何在没有PHP Semaphore的PHP中实现信号量?

我怎样才能实现共享内存变量在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哈希的唯一密钥与试捕捞周围似乎工作。

我发现

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

所以1个重复条目我认为它没有工作,但这是因为他们是:

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

(首都GRIN)

回答

3

这可以通过MySQL来实现。

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

否则,如果在表中的字段被列为唯一的,那么在下次会议上试图写入同一个URL表,他们会得到一个错误,你可以捕捉这个错误并继续,因为没有必要做如果条目已经在那里,任何东西。浪费的唯一时间是两个或更多会话创建相同URL的可能性,结果仍然是一条记录,因为数据库不会再次添加相同的唯一URL。

正如评论中所述,由于URL的长度可能很长,并且固定长度的唯一散列可以帮助解决该问题。

+0

这是一个额外的存储大,但也许你可以使用一个独特的哈希来代替? – Jacob 2011-03-08 00:14:21

+0

锁定整个表有点苛刻,在1锁期间,我可能有N个进程无法写入(来自不同的uris)。不能使uri具有唯一性:唯一字段有最大长度。一个独特的散列很有趣,也许这也是美味。在这里你看到混合数据库请求:http://leau.co/wp-content/blogs.dir/21/files/wp-favicons/cache/DEBUG.LOG – edelwater 2011-03-08 00:16:35

+0

因为我不知道是否存在uri记录它可能会像这样(A)更新记录中的LOCK其中uri_hash = md5(uri)try catch(B)如果存在则读取(C)如果存在release A(D)如果不存在则执行处理,写入和释放A - :) – edelwater 2011-03-08 00:21:44

1

还有其他的共享PHP中的内存模块(例如shmopAPC),但我认为你所说的是有一个问题依赖于非标准/不是p重新安装库。

我的建议是,在你去做“其他操作”之前,你需要在数据库中输入一个条目,可能是“编译”状态(或某些东西),所以你知道它仍然不可用。这样,您就不会遇到获取多个条目的问题。我也可以确定你使用的事务是可用的,所以你的提交是原子的。

然后,当你的“其他行动”完成后,更新数据库条目“可用”,并做到这一点是其他任何你需要做的。