PHP中的fopen文件锁定(阅读器/写入器类型的情况) [英] fopen file locking in PHP (reader/writer type of situation)

查看:140
本文介绍了PHP中的fopen文件锁定(阅读器/写入器类型的情况)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景,一个PHP进程每秒写一个文件大约3次,然后几个PHP进程正在读这个文件.

I have a scenario where one PHP process is writing a file about 3 times a second, and then several PHP processes are reading this file.

此文件本质上是缓存.我们的网站进行非常持久的轮询,以获取不断变化的数据,我们不希望每个访问者每次轮询都访问数据库,因此我们有一个cron进程,该进程每秒读取数据库3次,处理数据,并将其转储到轮询客户端可以读取的文件中.

This file is esentially a cache. Our website has a very insistent polling, for data that changes constantly, and we don't want every visitor to hit the DB every time they poll, so we have a cron process that reads the DB 3 times per second, processes the data, and dumps it to a file that the polling clients can then read.

我遇到的问题是,有时打开文件进行写入需要很长时间,有时甚至需要2-3秒.我假设发生这种情况是因为它被读取(或某种东西)锁定了,但是我没有任何确凿的方式来证明这一点,另外,据我从文档中了解到的那样, PHP不应锁定任何内容. 这种情况每2-5分钟发生一次,因此非常普遍.

The problem I'm having is that, sometimes, opening the file to write to it takes a long time, sometimes even up to 2-3 seconds. I'm assuming that this happens because it's being locked by reads (or by something), but I don't have any conclusive way of proving that, plus, according to what I understand from the documentation, PHP shouldn't be locking anything. This happens every 2-5 minutes, so it's pretty common.

在代码中,我没有进行任何 锁定,并且我几乎不在乎该文件的信息是否损坏,读取失败或数据是否更改.阅读中间. 不过,我确实很在意,如果写操作基本上需要2秒钟,因为该过程必须每秒进行三秒钟,所以现在跳过了几下节拍.

In the code, I'm not doing any kind of locking, and I pretty much don't care if that file's information gets corrupted, if a read fails, or if data changes in the middle of a read. I do care, however, if writing to it takes 2 seconds, esentially, because the process that has to happen thrice a second now skipped several beats.

我正在使用以下代码编写文件:

I'm writing the file with this code:

$handle = fopen(DIR_PUBLIC . 'filename.txt', "w");
fwrite($handle, $data);
fclose($handle);

我正直接用以下内容阅读它:

And i'm reading it directly with:

file_get_contents('filename.txt')

(它没有作为静态文件直接提供给客户端,我收到了一个常规的PHP请求,该请求读取该文件并对其进行一些基本的操作)

(it's not getting served directly to the clients as a static file, I'm getting a regular PHP request that reads the file and does some basic stuff with it)

该文件约为11kb,因此无需花费大量时间进行读取/写入.不到1毫秒.

The file is about 11kb, so it doesn't take a lot of time to read/write. Well under 1ms.

这是发生问题时的典型日志条目:

This is a typical log entry when the problem happens:

  Open File:    2657.27 ms
  Write:    0.05984 ms
  Close:    0.03886 ms

不确定是否相关,但是读取是通过apache在常规Web请求中进行的,但是写入是Linux的cron进行的常规命令行" PHP执行,不是通过Apache.

Not sure if it's relevant, but the reads happen in regular web requests, through apache, but the write is a regular "command line" PHP execution made by Linux's cron, it's not going through Apache.

任何可能导致打开文件的时间如此延迟的想法是什么?
有什么指针可以帮助我查明实际原因吗?

Any ideas of what could be causing this big delay in opening the file?
Any pointers on where I could look to help me pinpoint the actual cause?

或者,您能想到我可以做些什么来避免这种情况吗?例如,我希望能够将fopen设置为50毫秒的超时时间,如果它没有打开文件,它将跳过前面的内容,并让cron的下一次运行对其进行处理.

Alternatively, can you think of something I could do to avoid this? For example, I'd love to be able to set a 50ms timeout to fopen, and if it didn't open the file, it just skips ahead, and lets the next run of the cron take care of it.

再次,我的首要任务是使cron跳动三次,其他所有都是次要的,因此任何想法,建议和任何事物都非常受欢迎.

Again, my priority is to keep the cron beating thrice a second, all else is secondary, so any ideas, suggestions, anything is extremely welcome.

谢谢!
丹尼尔

Thank you!
Daniel

推荐答案

我可以想到3种可能的问题:

I can think of 3 possible problems:

  • 该文件在较低的php系统调用下被读写时被锁定,而您不知道该文件.这样应该最多将文件阻塞1/3s.你得到的那段时间更长.
  • fs缓存启动一个fsync(),整个系统将阻止对磁盘的读/写操作,直到完成该操作为止.作为解决方法,您可以尝试安装更多的RAM或升级内核或使用更快的硬盘
  • 您的高速缓存"解决方案并未分发,并且每秒击中整个系统中性能最差的硬件的次数……这意味着您不能仅仅通过增加更多的机器(仅通过增加硬盘驱动器)来进一步扩展它.速度.您应该查看内存缓存或APC,甚至共享内存 http://www.php.net/manual/zh/function.shm-put-var.php

我能想到的解决方案:

  • 将该文件放在ramdisk中 http://www.cyberciti.biz/faq/howto-create-linux-ram-disk-filesystem/.这应该是避免如此频繁地击打磁盘而无需进行其他重大更改的最简单方法.
  • 使用内存缓存.当在本地使用时,它非常快,可扩展性很好,被大型"玩家使用. http://www.php.net/manual/zh/book.memcache. php
  • 使用共享内存.它是为您要在此处尝试执行的操作而设计的...具有共享内存区域" ...
  • 更改cron调度程序以减少更新,也许实现某种事件系统,所以它只会在必要时更新缓存,而不是按时间更新
  • 使写入"脚本写入3个不同的文件,并使读取器"从其中一个文件中随机读取.这可以允许在更多文件中分配"锁定,并且可以减少在写入某个文件时锁定该文件的机会...但是我怀疑它会带来任何明显的好处.
  • put that file in a ramdisk http://www.cyberciti.biz/faq/howto-create-linux-ram-disk-filesystem/ . This should be the simplest way to avoid hitting the disk so often, without other major changes.
  • use memcache. Its very fast when used locally, it scales well, used by "big" players. http://www.php.net/manual/en/book.memcache.php
  • use shared memory. It was designed for what you are trying to do here... having a "shared memory zone"...
  • change the cron scheduler to update less, maybe implement some kind of event system, so it would only update the cache when necessary, and not on a time basis
  • make the "writing" script write to 3 files different, and make the "readers" read from one of the files, randomly. This may allow a "distribution" of the loking across more files and it may reduce the chances that a certain file is locked when writing to it... but i doubt it would bring any noticeable benefits.

这篇关于PHP中的fopen文件锁定(阅读器/写入器类型的情况)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆