如何从Azure页面Blob读取并发写入?

时间:2016-01-11 22:50:20

标签: java azure azure-storage azure-storage-blobs

我正在调用Azure Storage SDK for Java(v4.0.0)中的downloadRange - 函数来下载Page Blob的部分内容,例如: downloadRange(0, 1000, os, null, null, null)。另一个进程,一个编写器,写入页面blob的末尾。如果写入与downloadRange并发 - 调用并且downloadRange在内部重试(HTTP GET),则会生成带有以下文本的StorageException:“使用HTTP条件头指定的条件(s)未得到满足。“。

如果不发生这种情况,是否可以执行downloadRange读取操作?就应用而言,在最后一页之前访问字节是安全的。

伪代码如下(使用scala):

val blob = container.getPageBlobReference(blobName)
val baos = new ByteArrayOutputStream()
blob.downloadRange(0, totalSize, baos, null, null, null)

更新

根据以下评论进行澄清。用例有点特殊,因为已知读取字节范围是安全的,即它只读取blob中未同时写入的字节范围。写入仅附加到blob的末尾。问题是如何使用downloadRange或Azure存储SDK的任何其他部分来访问具有并发写入的blob,即使在网络问题(丢包,传输速度慢等)的情况下也是如此。

2 个答案:

答案 0 :(得分:4)

此答案基于您可以阅读的评论主题。

在这种特殊情况下,错误发生在重试而不是第一次调用。当存储库重试下载时,if-match会被设置,因为在重试时我们必须保证blob没有改变以保持一致性。否则,如果在这些调用之间设置了新的blob,我们将获得旧的一半和新的一半。从图书馆的角度来看,由于我们没有知识,如果blob已经改变,后续的读取将是安全的,我们必须强制执行此操作。没有办法禁用它。

在这种特殊情况下,存在频繁连接失败,并发写入和读取安全性预知的非常独特的组合。这是我一直认为非常罕见的事情。连接失败将是最罕见的部分,因此可能需要更多的调查(也许是另一个问题的主题)。

在这种特殊情况下,我建议尽一切可能减少网络开放的时间。减少此时间意味着首先减少网络故障,降低blob发生更改的可能性,如果重试确实发生,因为小型下载只需要更少的时间。将读取分解为较小的块可能是实现此目的的最佳途径。同样,您可能只想在catch语句中手动重试此部分下载以解决此错误。

答案 1 :(得分:0)

问题StorageException似乎是由于没有为类AccessCondition的函数downloadRange设置参数CloudBlob而引起的。

关于Azure存储并发,我建议使用官方文档Managing Concurrency in Microsoft Azure Storage。 C#中有一些代码示例作为参考。您可以尝试引用the Javadocs of Azure Storage SDK并在Java中翻译这些代码。

如有任何疑虑,请随时告诉我。