我正在阅读IOCP,从我目前了解的情况来看,asynchronous写入仅适用于写入文件的上下文。 通过“文件”,我不是只是磁盘文件,而是Windows上的“文件”types的输出设备。
我打算以某种方式使用IOCP来实现从客户端接收消息的服务器,然后将这些消息asynchronous地写入数据库(MySQL或SQLite)。 但据我所知,IOCP中的asynchronous写入涉及将数据写入设备驱动程序 – 而“设备驱动程序”的提及似乎排除了使用IOCP和asynchronous写入数据库的可能性,因为存在从应用程序编写者的angular度来看,没有涉及到写入数据库的“设备驱动程序”。
那么,IOCP真的可以帮助实现写入数据库的服务器吗? 我有一种唠叨的感觉,我误解了一些东西。
如果IOCP在这种情况下无法提供帮助,那么对于实现在Windows上对数据库执行asynchronous写入的服务器,我应该看看有什么build议吗?
通常一个数据库会给你一个你用来写入的API。 这通常隐藏了它所做的所有复杂的事情。 有时候,这个API可能是通用的,可以与大量的数据库一起工作,比如OLE-DB和ODBC,有时API也可能是数据库特定的。
您使用的数据库不太可能会暴露一个足够低的IO使用IOCP的API,尽管它可能会在内部使用IOCP。
你可能想问的是,我可以使用异步写入来写入我的数据库吗?也就是说,你可以在不阻止正在执行“关闭”的线程的情况下触发一个数据库写入。
当IOCP的“友好的”数据库API将是很好的,当你的服务器的其余部分使用IOCP与自己的日志文件和套接字读/写通常最好的,你可以得到的是使用线程池,让你发出阻止数据库API要求的调用,而不会阻塞服务器执行的其他工作。 我倾向于称之为“业务逻辑线程池”,它与我用于所有非阻塞I / O的IOCP线程池是分开的。
我写了一些关于构建使用这种设计写入数据库的服务器的文章,可以在这里找到代码和文章的链接。
Io完成端口是一种多功能的机制,可以通过多种方式实现可扩展性。
在“最佳”情况下,Io完成端口与正在被重叠的Io使用的OS句柄相关联。 但实际上这并不是一个要求:Io Completion Port机制足以提供可扩展性,即使所有使用的API都被阻塞和/或不公开所需的句柄。
在一个非常简单的模型中,可以使用CreateIoCompletionPort
– 调用PostQueuedCompletionStatus
来创建用户定义的“作业”。 创建一个工作线程池,它们都在GetQueuedCompletionStatus
循环 – 在处理排队作业时只需在工作线程中调用阻塞Io例程。 每当一个工作线程阻塞任何内核函数时,Io完成端口机制将看到并发计数低,并释放另一个工作线程。
显然,用这种方式,活动工作线程的数量可以超过并发计数,但是,假设这些工作是对称的,当线程返回到GetQueuedCompletionStatus调用时,它应该很快地自行解析。
当你写入文件时,它们可以帮助你在任何地方发生,而不想在发生任何事情时阻塞。 很难想象一个数据库想要这样做,除了编写完整无关紧要的文本日志文件。
IOCP在实施数据库时可以帮助很大。
IOCP结合FILE_FLAG_NO_BUFFERING和FILE_FLAG_WRITE_THROUGH和正确对齐的块使数据库引擎控制缓存行为,避免不必要的重复缓存和块复制,以正确的顺序获得写入,同时可以在任何写入的控制等。
当然,为了使用这些特性,需要实现数据库,使用SQLite和Mysql可以获得其他的功能。
有关这将如何帮助实施数据库的更多详细信息,Gray和Reuter的“Transaction Processing:Concepts and Techniques”是一个很好的参考。