c - 并发访问的光泽文件锁定
问题描述
我正在尝试开发一个应用程序,该应用程序将在链接到共享 Lustre 存储的多台计算机上运行,执行各种操作,包括但不限于:
- 将数据附加到文件。
- 从文件中读取数据。
- 读取和写入文件,修改其所有内容都会传递一定的偏移量。
- 读取和写入文件,在特定偏移处修改其内容。
如您所见,基本的 I/O 是人们所希望的。
由于大多数情况下它是并发的,我应该需要某种锁定以允许安全地进行不同的写作,但我已经看到 Lustre 默认不支持flock(2)s(我不确定我想要在 fcntl(2) 上使用它,我想我会的),而且我还没有看到任何关于 fcntl(2) 的信息来确认它的支持。
研究它主要导致我阅读了很多关于使用 Lustre 进行 I/O 优化的论文,但这些论文通常解释了他们的硬件/软件/网络的结构是如何工作的,而不是解释它是如何在代码中完成的。
那么,我可以在 Lustre 中使用 fcntl(2) 吗?我应该使用它吗?如果不是,还有哪些其他替代方法可以允许不同的客户端执行数据的并发修改?
还是有可能?(我在 Lustre 票证中看到 mmap 是可能的,所以 fcntl 也应该可以工作(声明背后没有逻辑),但我可能想知道一些限制。)
我将继续编写一个测试应用程序来检查它,但我认为我仍然应该询问是否有更好的替代方案(或者我应该注意它的功能是否存在限制,因为我的测试将受到限制并且我们不希望未知的限制成为开发过程后期的问题)。
谢谢,
编辑: LustreOne 已正确回答了基本问题,在这里我提供了有关我的用例的更多具体信息,以允许人们添加有关 Lustre 并发访问的相关附加信息。
Lustre 客户端将成为其他应用程序的服务器。这些应用程序的客户端每个都有自己的文件集,但我们希望支持允许客户端同时从多台机器登录到他们的客户端空间,为此,我们需要允许并发文件读取和写入。
然而,这些总是占总 I/O 操作的一小部分。
虽然 LustreOne 的回答中提供了非常有趣的见解,但其中并不多适用于这个用例(或者更确切地说,它们确实适用,但可能不希望增加整个系统的复杂性以影响性能)。
也就是说,对于目前考虑的用例,我相信它可以对某些人有很大帮助,以及以后的我们自己。然而,我们现在寻求的更多的是一种方法,可以轻松地让两个节点或一个节点响应两个请求的线程来修改数据,让一个通过并检测冲突,有效地防止相关客户端。
我相信文件锁定对于那个用例来说就足够了,但是更喜欢字节锁定,因为一些最关心的文件被一些客户端不间断地附加,并被其他人读取/修改到最后。
但是,从我从 LustreOne 的回答中了解到的情况来看:
也就是说,如果您的应用程序知道它在做什么,则对此没有严格的要求。Lustre 已经将非重叠写入保持一致,并且还可以处理并发 O_APPEND 写入。
后一个案例已经由 Lustre 开箱即用地管理。
关于什么是最好的选择有什么意见吗?在完整文件上使用简单的flock()就足够了吗?
请注意,某些文件也将具有索引,可用于确定数据的可用性而无需锁定任何数据文件,是否应该使用或字节锁定足够快,以避免增加代码库大小以支持这两种情况?
最后提及mmap
。我很确定它不太适合我们的用例,因为我们有这么多文件和很多客户端,所以 OST 可能无法缓存太多,但可以肯定的是......是否应该使用它,如果是这样,如何?^^
抱歉这么冗长,这是我的缺点之一。:/
祝你今天过得愉快,
解决方案
您应该使用“-o flock”挂载选项挂载所有客户端,以启用全局一致锁定。然后flock() (我认为fcntl() 锁定)会起作用。
也就是说,如果您的应用程序知道它在做什么,则对此没有严格的要求。Lustre 已经将非重叠写入保持一致,并且还可以处理并发 O_APPEND 写入。但是,由于 Lustre 必须对追加进行内部锁定,如果有很多不同的客户端同时追加到同一个文件,这可能会严重影响写入性能。(请注意,如果仅附加一个客户端,这不是问题)。
如果您自己编写应用程序,那么您可以做很多事情来提高性能: - 让一些中央线程为每个写入器分配一个“写入槽号”(本质上是一个递增的整数),然后客户端写入偏移量 = 记录大小 * 插槽号。除了分配槽号(可以分批完成以获得更好的性能)之外,客户端之间没有争用。在大多数 HPC 应用程序中,线程使用 MPI 等级作为插槽编号,因为它是唯一的,并且同一节点上的线程通常会分配到相邻的插槽,因此 Lustre 可以进一步聚合写入。如果您使用线程可能产生可变数量的记录的生产者/消费者模型,那将不起作用。- 使 IO 记录大小为 4KiB 的倍数,以避免线程之间的争用。否则,客户端或服务器将被迫对磁盘块中的部分记录进行读-修改-写,这是低效的。- 根据您的工作流程是否允许,而不是对同一个文件进行读取和写入,将一堆记录写入一个文件,然后将文件作为一个整体处理并写入第二个文件可能会更有效文件。并不是说 Lustre 不能对单个文件进行并发读写,但这会导致可以避免的不必要的争用。然后将文件作为一个整体处理并写入第二个文件。并不是说 Lustre 不能对单个文件进行并发读写,但这会导致可以避免的不必要的争用。然后将文件作为一个整体处理并写入第二个文件。并不是说 Lustre 不能对单个文件进行并发读写,但这会导致可以避免的不必要的争用。
推荐阅读
- python - Python - 看不到我正在输入的内容,灰色背景
- java - 无法使用图像加载器加载图像
- audiokit - 音频文件的细粒度 FFT 分析
- amazon-web-services - aws-cdk 中的 !Ref 函数
- mongodb - $lookup 当外部字段是一个数组
- ios - 每次运行 cellforrow 方法时都必须刷新 Firebase 数据吗?
- ios - 为 UIImage 获取错误的 SHA 256 值
- java - Java在Maven项目中找不到库
- opencv - 如何使用 readNet(或 readFromDarknet)而不是 readNetFromCaffe?
- c - 检查地址在 Linux 内核中是否有效(NULL 检查除外)