如何解决等到新的 Sqlite 事件发生
我希望 PHP 在 sqlite 数据库中插入新行时等待并执行操作。
当然,我们可以这样做:
while (true) {
usleep(200*1000); // wait 200 ms
$db->query('SELECT id ....'); // check if a new row (with a new id) has been inserted
}
但我想避免每 200 毫秒无故查询一次数据库,因为这会浪费资源。
上下文:我想在长轮询方案中执行此操作,并避免让 PHP 工作程序/守护程序不断运行:客户端与服务器建立连接,服务器不会立即响应并等待新的事情发生数据库。
注意:之前我已经使用过WebSocket,但是对于这个特定的项目,我不能使用它。
解决方法
您说过所有可能更改您的数据库的 PHP 脚本都可以启动一个进程来发出更改信号。这意味着您不必经常轮询数据库,您可以轮询其他一些简单的东西。
假设每次对数据库进行更改时,都会更新一个包含时间信号的文件。一个可以做到这一点的 PHP 函数是:
function signalDatabaseChange()
{
$success = FALSE;
if ($file = fopen('signal.json','w'))
{
$json = json_encode(["timeSignal" => hrtime(TRUE)]);
if (flock($file,LOCK_EX)) {
$success = fwrite($file,$json) > 0;
flock($file,LOCK_UN);
}
fclose($file);
}
return $success;
}
它将写入一个包含时间信号的小型 JSON 文件,同时在文件上持有排他阻塞锁。成功时返回 TRUE
,否则返回 FALSE
。您的应用程序应正确处理 FALSE
响应。
所以现在我们在服务器上有一个小 JSON 文件,它表示数据库更改的最新时间。可以在使用很少资源的情况下经常轮询此文件。
您暗示要使用长轮询。在这种情况下,请查看 using server-sent events。
您可以使用以下内容轮询 PHP 代码中的 signal.json
:
function getTimeSignal()
{
$timeSignal = FALSE;
if ($file = fopen('signal.json','r'))
{
if (flock($file,LOCK_SH)) {
$json = fread($file,filesize('signal.json'));
flock($file,LOCK_UN);
$timeSignal = json_decode($json);
}
fclose($file);
}
return $timeSignal;
}
这将返回存储的时间信号,或 FALSE
。通过使用文件锁定,在这两个函数中,您可以保证文件中始终存在有效的时间戳。
当客户端检索到一个新的时间信号时,它可以使用它以及它获得的前一个时间信号,向服务器询问在这两个信号之间发生的所有数据库更改。
此方法假定时间信号检查比时间信号更新要多得多。只有这样才值得使用这种方法。
我使用了一个文件来存储时间信号,但这不是唯一的选择。时间信号可以存储在存储器中。在几乎所有情况下,这都需要对 PHP 配置进行一些控制,考虑到您已经制定的所有约束,我不确定您是否有。
在此示例代码中,我使用了时间信号。这几乎意味着您的数据库也存储这些时间信号。情况可能并非如此。当然,您可以添加它们,但您也可以使用其他东西。我不知道该建议什么,但它可以作为最新聊天消息的索引,例如在聊天应用中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。