1

我正在阅读 IOCP,据我所知,异步写入仅适用于写入文件的上下文。我所说的“文件”不仅仅指磁盘文件,而是指 Windows 上的“文件”类型的输出设备。

我计划以某种方式使用 IOCP 来实现一个服务器,该服务器从客户端获取消息,然后将这些消息异步写入数据库(MySQL 或 SQLite)。但是,据我了解,IOCP 中的异步写入涉及将要写入的数据传递给设备驱动程序——而且“设备驱动程序”的提及似乎排除了在数据库上使用 IOCP 和异步写入的可能性,因为有从应用程序编写者的角度来看,不涉及写入数据库的“设备驱动程序”。

那么,IOCP 真的可以帮助实现写入数据库的服务器吗?我有一种唠叨的感觉,我误解了一些东西。

如果 IOCP 在这种情况下无法提供帮助,对于在 Windows 上实现对数据库进行异步写入的服务器,我应该考虑什么建议?

4

4 回答 4

2

通常,数据库会给你一个 API,你可以用它来写入它。这通常隐藏了它所做的所有复杂事情。有时该 API 可能是通用的并且可以与许多数据库一起使用,例如 OLE-DB 和 ODBC,有时 API 可能是特定于数据库的。

您使用的数据库不太可能公开低级别的 API 以使用 IOCP,尽管它可能在内部使用 IOCP。

您可能想问的是,我可以使用异步写入来写入我的数据库吗,也就是说,您能否在不阻塞执行“触发”的线程的情况下触发数据库写入。

虽然当您的服务器的其余部分使用 IOCP 与其自己的日志文件和套接字读/写通信时,IOCP“友好”数据库 API 会很好,但您可以获得的最好的方法是使用线程池来允许您发出阻止数据库 API 需要的调用,而不会阻止服务器执行的其余工作。我倾向于将其称为“业务逻辑线程池”,它与我用于所有非阻塞 I/O 的 IOCP 线程池是分开的。

我写了一些文章来构建使用这种设计来写入数据库的服务器,并且可以在此处找到文章的代码和链接。

于 2010-08-15T06:24:28.847 回答
1

Io Completion Ports 是一种通用机制,可用于多种方式来实现可扩展性。

在“最佳”情况下,Io 完成端口与重叠 Io 使用的操作系统句柄相关联。但这实际上根本不是必需的:Io 完成端口机制足够通用,可以提供可伸缩性,即使使用的所有 API 都是阻塞的和/或不公开所需的句柄。

在一个非常简单的模型中,可以使用CreateIoCompletionPort- 调用PostQueuedCompletionStatus来创建用户定义的“作业”。创建一个所有循环的工作线程池GetQueuedCompletionStatus- 并在处理排队作业时简单地在工作线程内调用阻塞 Io 例程。每当其中一个工作线程阻塞在任何内核函数上时,Io 完成端口机制将看到并发计数较低,并释放另一个工作线程。

显然,使用这种方式,活动工作线程的数量可能会超过并发计数,但是,假设作业是对称的,当线程返回到它的“GetQueuedCompletionStatus”调用时,它应该会很快自行解决。

于 2010-08-15T18:18:17.523 回答
0

IOCP 在实现数据库时可以提供很大帮助。

IOCP 结合 FILE_FLAG_NO_BUFFERING 和 FILE_FLAG_WRITE_THROUGH 以及正确对齐的块让数据库引擎控制缓存行为,避免不必要的重复缓存和块副本,以正确的顺序获取写入,控制哪些写入可以同时进行,等等。

当然,需要实现数据库才能使用这些功能,使用 SQLite 和 Mysql 你会得到其他东西。

有关这将如何帮助实现数据库的更多详细信息,Gray 和 Reuter 的“事务处理:概念和技术”是一个很好的参考。

于 2010-08-15T04:24:51.240 回答
0

当您写入文件并且不想在发生任何事情时阻塞时,它们可以在任何地方提供帮助。很难想象一个数据库想要这样,除了可能在编写完整性并不重要的文本日志文件时。

于 2010-08-15T03:30:25.283 回答