将大型 Page Blob 的页范围进行分段
Windows Azure
存储支持一种 Blob
类型,即 Page Blob。Page
Blob 通过仅将已写入但未清除的页存入物理存储,
来有效存储稀疏数据。每页大小为 512
字节。Get
Page Ranges REST
服务调用将返回包含有效数据的所有连续页范围的列表。在 Windows Azure
存储客户端库中,GetPageRanges
方法提供此功能。
如果服务处理请求的时间过长,Get Page Ranges在某些情况下可能会失败。与所有
Blob REST API 类似,Get Page Ranges使用超时参数,此参数用于指定允许请求的时间,包括通过网络进行读/写。但是,仅给服务器一段固定时间来处理请求和开始发送响应。如果此服务器超时已过,则即使还未到
API 超时参数指定的时间,请求也会失败。
在一个高度分散但具有大量写入的 Page Blob
中,填充 Get PageRanges
返回的列表可能要比服务器超时的时间更长,所以请求将失败。因此,如果应用程序使用的模式中含有大量 Page Blob写入,并且您想要调用
GetPageRanges,建议应用程序应一次检索一部分页范围。
例如,假设 500 GB
的 Page Blob
通过 500,000
次写入来填充整个 Blob。默认情况下,存储客户端指定
Get PageRanges 操作的超时时间为 90
秒。如果 Get PageRanges
未在服务器超时间隔内完成,调用将失败。这一问题可以通过分组提取范围(比如
每组50 GB)的方式来解决。这会将工作拆分成
10 个请求。其中每个请求都在各自的服务器超时间隔内单独完成,确保能够成功检索全部范围。
为了确保所有请求都可以在服务器超时间隔内完成,请分段提取范围,每段 150 MB。这样,即使对于最散分布的
Page Blob 来说也很安全。如果 Page Blob
分布较集中,可以使用较大分段。
客户端库扩展
下面我们提供了一个简单的扩展方法,使存储客户端可以通过提供
rangeSize
参数将请求拆分成给定大小的范围来解决此问题。生成的 IEnumerable
对象在需要时才循环访问所有页范围,从而根据需要进行服务调用。
由于将请求拆分成了多个范围,任何超出
rangeSize
边界的页范围都会在结果中拆分成多个页范围。因此对于大小为 10 GB
的分段范围,以下 40 GB
的范围
[0 – 42949672959]
将拆分成四个 10 GB
的范围:
[0 – 10737418239]
[10737418240 –21474836479]
[21474836480 –32212254719]
[32212254720 –42949672959].
若分段范围大小为 20 GB,则上述范围将仅拆分成两个范围。
请注意,通过将BlobRequestOptions
对象指定为参数,可以使用自定义超时,但下面的方法不使用任何重试策略。对每个服务调用单独应用指定的超时。如果由于某种原因导致服务调用失败,GetPageRanges
将抛出异常。
<span style="font-size:14px;">namespace Microsoft.WindowsAzure.StorageClient
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.WindowsAzure.StorageClient.Protocol; /// <summary>
/// Class containing an extension method for the <see cref="CloudPageBlob"/> class.
/// </summary>
public static class CloudPageBlobExtensions
{
/// <summary>
/// Enumerates the page ranges of a page blob, sending one service call as needed for each
/// <paramref name="rangeSize"/> bytes.
/// </summary>
/// <param name="pageBlob">The page blob to read.</param>
/// <param name="rangeSize">The range, in bytes, that each service call will cover. This must be a multiple of
/// 512 bytes.</param>
/// <param name="options">The request options, optionally specifying a timeout for the requests.</param>
/// <returns>An <see cref="IEnumerable"/> object that enumerates the page ranges.</returns>
public static IEnumerable<PageRange> GetPageRanges(
this CloudPageBlob pageBlob,
long rangeSize,
BlobRequestOptions options)
{
int timeout; if (options == null || !options.Timeout.HasValue)
{
timeout = (int)pageBlob.ServiceClient.Timeout.TotalSeconds;
}
else
{
timeout = (int)options.Timeout.Value.TotalSeconds;
} if ((rangeSize % 512) != 0)
{
throw new ArgumentOutOfRangeException("rangeSize", "The range size must be a multiple of 512 bytes.");
} long startOffset = 0;
long blobSize; do
{
// Generate a web request for getting page ranges
HttpWebRequest webRequest = BlobRequest.GetPageRanges(
pageBlob.Uri,
timeout,
pageBlob.SnapshotTime,
null /* lease ID */); // Specify a range of bytes to search
webRequest.Headers["x-ms-range"] = string.Format(
"bytes={0}-{1}",
startOffset,
startOffset + rangeSize - 1); // Sign the request
pageBlob.ServiceClient.Credentials.SignRequest(webRequest); List<PageRange> pageRanges; using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
// Refresh the size of the blob
blobSize = long.Parse(webResponse.Headers["x-ms-blob-content-length"]); GetPageRangesResponse getPageRangesResponse = BlobResponse.GetPageRanges(webResponse); // Materialize response so we can close the webResponse
pageRanges = getPageRangesResponse.PageRanges.ToList();
} // Lazily return each page range in this result segment.
foreach (PageRange range in pageRanges)
{
yield return range;
} startOffset += rangeSize;
}
while (startOffset < blobSize);
}
}
}</span>
用法示例:
pageBlob.GetPageRanges(10* 1024 * 1024 * 1024 /* 10 GB */, null);
pageBlob.GetPageRanges(150* 1024 * 1024 /* 150 MB */, options /* custom timeout in options */);
总结
对于某些分段的 Page Blob,GetPageRangesAPI
调用可能不会在最大服务器超时间隔内完成。为解决这一问题,一次可以提取一部分页范围,
完成后再提取下一部分,这样就减少了单个服务调用花费的时间。我们提出一种扩展方法,能够在 Windows Azure
存储客户端库中实施此技术。
Michael Roberson
本文翻译自:
将大型 Page Blob 的页范围进行分段的更多相关文章
- Windows Azure Storage (19) 再谈Azure Block Blob和Page Blob
<Windows Azure Platform 系列文章目录> 请读者在参考本文之前,预习相关背景知识:Windows Azure Storage (1) Windows Azure St ...
- SharePoint 2013 对二进制大型对象(BLOB)进行爬网
本文是参考MSDN文档做的示例,SharePoint 2013搜索二进制对象(BLOB),通过外部内容类型的方式将外部数据与SharePoint相关联,修改BCD模型,使SharePoint能够爬网外 ...
- [译]用AngularJS构建大型ASP.NET单页应用(一)
原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 渣 ...
- [译]用AngularJS构建大型ASP.NET单页应用(三)
原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single A ...
- [译]用AngularJS构建大型ASP.NET单页应用(二)
原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 客 ...
- SharePoint 2013 使用 RBS 功能将二进制大型对象 BLOB 存储在内容数据库外部。
为每个内容数据库设置 BLOB 存储 启用并配置 FILESTREAM 之后,请按照以下过程在文件系统中设置 BLOB 存储.必须为要对其使用 RBS 的每个内容数据库设置 BLOB 存储. 设置 ...
- Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储
一,引言 上一篇文章,我们介绍到在实际项目中系统会产生大量的日志文件,用户上传的头像等等,同时也介绍到可以使用Azure Blob Storage 来存储项目中的一些日志文件,用户头像,用户视频等等. ...
- kubernetes1.4新特性:支持两种新的卷插件
背景介绍 在Kubernetes中卷的作用在于提供给POD持久化存储,这些持久化存储可以挂载到POD中的容器上,进而给容器提供持久化存储. 从图中可以看到结构体PodSpec有个属性是Volumes, ...
- 刨根究底字符编码之七——ANSI编码与代码页(Code Page)
ANSI编码与代码页(Code Page) 一.ANSI编码 1. 如前所述,在全世界所有国家和民族的文字符号统一编码的Unicode编码方案问世之前,各个国家.民族为了用计算机记录并显示自己的字符, ...
随机推荐
- Git学习资料整理
Git作为一个优秀的版本控制系统,是我们开发人员必须要学会使用的一个工具,接触git一年多以来,也看了不少相关资料,今天把我所看过的一些学习资源整理一下. Git入门当然首推廖雪峰廖老师的教程:Git ...
- 新版福昕阅读器(Foxit Reader)启动速度慢解决办法
新版福昕阅读器(FoxitReader)启动速度慢解决办法之前喜欢使用福昕阅读器的原因就是看中了其小巧,可是最近版本的阅读器打开速度变得慢了很多(不是电脑配置问题),比AdobeReader还要慢,这 ...
- win7-64bit 下oracle11g plsql 的正确安装
本人在PC机上安装了Oracle 11g 版本号的数据库服务,通过PL/SQL连接数据库时总是无法连接,位的oracle客户端工具instantclient进行转换,另外一种plsql的不能安装到文件 ...
- 将activity设置成dialog样式如何设置窗口大小
具体做法和dialog窗口的设置类似,只需要在onCreate方法中,加入下列代码,既可以控制大小! // 设置窗体大小 ScreenUtil.getScreenWidth(LoadActivity ...
- logcat使用
做android有些日子了,只是对主要的logcat的具体使用方法还是非常模糊,今天有空,学习一下. logcat能够在adb中使用,也能够直接在命令行下使用. logcat [options] [f ...
- java byte数组与int,long,short,byte转换
public class DataTypeChangeHelper { /** * 将一个单字节的byte转换成32位的int * * @param b * byte * @return conver ...
- Java基础知识强化30:String类之String的特点(String为什么是final)
1. String字符串特点: 一旦被赋值,字符串值就不能改变. 这里String是final修饰的,具有不可继承性. 2. 为什么String是final? 主要是为了"效率" ...
- JNI 详细使用步骤 上手示例
1.定义本地native方法 定义本地方法,通常情况下,应单独定义一个类来封装所有native方法 /** 存放native方法的类 */ public class MyNativeMethods { ...
- C# 面向对象 , 抽象基类
抽象基类 关键字, abstract abstract class SSS { public void aaa() { } } 作为抽象基类, 只能在 继承关系 中 担任父类的角色,不能出现在其他地 ...
- 用timer控件实现sleep效果
有时候我们需要代码延迟执行,这就需要用到Thread.Sleep()这个方法,但这个方法在主线程使用时会造成界面假死.使用timer控件既能达到代码延迟执行的效果,又不会有假死的困扰. 假设我们需要在 ...