为啥 PHP 文件追加仅在 99.7% 的尝试中完全成功
Posted
技术标签:
【中文标题】为啥 PHP 文件追加仅在 99.7% 的尝试中完全成功【英文标题】:Why is PHP file append only wholly successful in 99.7% attempts为什么 PHP 文件追加仅在 99.7% 的尝试中完全成功 【发布时间】:2016-01-04 23:53:06 【问题描述】:我有一个在各种平台上运行的 javascript 应用程序。 (我尝试使用 caniuse.com 尽可能多地保留客户端设备列表,包括早期的 android 手机和早期的 iPhone)。
每次客户端应用程序的数据更改时,新数据都会附加到服务器上的纯文本日志文件中。附加是大约 20 到 70 个字符之间的单个字符串。
问题
每隔一段时间 - 大约 250 次中的一次 - 附加的前 6 到 20 个字符会离开。
客户端设备上的 JavaScript 应用程序通过 XmlHttpRequest 将数据发送到 Windows PC 上的 php 5.5.10,然后写入 NAS 已安装分区上的磁盘文件(作为 Windows 驱动器盘符安装在 PC 上)。
PHP 在 Windows 7 上的 Mongoose Web 服务器上运行,然后将数据存储在服务器网络上的家用网络附加存储设备的硬盘上。 (Debian Linux NAS 设备)NAS 有时可能需要几秒钟来启动硬盘。
只有一台客户端设备在使用任何给定的纯文本文件,但在任何给定时间最多可能有 10 台客户端设备访问它们各自的纯文本文件。
问题
如果我修复服务器+NAS 组合上的延迟,它会消失吗? (例如,通过将文件本地放在服务器上)
或者有没有办法通过使用新设施来保证写入?比如说,通过写入 SQLite 表而不是纯文本文件、Couchbase db 或 CouchDB 等。
只要客户端设备的参与保持为一个简单的 XmlHttpRequest,我就可以保留范围广泛的客户端设备。
【问题讨论】:
【参考方案1】:fwrite 的 PHP 文档说它是一个原子操作 - 要么应该写所有东西,要么什么都不写。
这表明它是 PHP 中的一个错误。
我已提交错误报告。
关于工作轮的任何想法?
(在今天的测试中,没有一个写入是部分的。12 个丢失,17 个发生乱序 - 即与客户端发送信息的顺序不同,总共 42 个)。
【讨论】:
我改变了 fopen($filename,"a") ; fwrite($stuff) ; fclose() 序列到 file_put_contents($filename, $stuff, FILE_APPEND | LOCK_EX) 这为进程添加了一个隐式文件锁,由 fclose() 释放。这应该使所有写入要么成功,要么完全失败。 (与目前的情况相反,它们偶尔会部分失败)【参考方案2】:我认为这里没有足够的信息,系统太多而信息太少。我能想到的唯一是它是一个并发问题。
如果您正在写入磁盘上的文件,如果两个请求同时进入会发生什么?如果您先阅读,然后再写入,则可能会导致第二个请求被第一个请求覆盖。例如:
Process 1 receives data Y.
Process 2 receives data Z.
Process 1 reads data X from the disk.
Process 2 reads data X from the disk.
Process 1 writes to the disk, data is now XY
Process 2 writes to the disk, data is now XZ
在此示例中,Y
丢失。
如果您使用数据库(mysql、Couch 等),则数据在读取和写入之间发生变化的影响应该不大。在我不得不阅读某些内容并编辑该确切内容的罕见情况下,我会使用类似于
的查询UPDATE table SET data = "XY" WHERE data = "X"
这意味着如果我读取 X 后数据发生了变化,它不会更新字段,这是我可以在代码中观察和处理的。
【讨论】:
以上是关于为啥 PHP 文件追加仅在 99.7% 的尝试中完全成功的主要内容,如果未能解决你的问题,请参考以下文章