问题表现
我们发现当PartitionKey或RowKey含有“%”字符时,应用Windows Azure Tables的服务将受到影响。
受此影响的API包括:Get entity, Merge entity, Update entity, Delete entity, Insert或Merge Entity,以及Insert或Replace Entity的API。如果任何上述API被调用时其PartitionKey或RowKey含有“%”,用户则将收到404 Not Found或者400 Bad Request的错误代码。此外,当用户调用Insert或Merge Entity以及Insert或Replace的API时,请求可能成功但所储存的字符串可能并不正确。
注意Insert Entity, Entity Group Transaction以及Query Entities的API不受影响,因为PartitionKey和RowKey并不是其URL路径的一部分。
根本原因
Windows Azure Table服务处理请求时会对URL路径部分重复解码,此时会错误地理解此含有“%”的字符串。注意URL的查询字符串部分以及HTTP正文部分中的字符串并不受此影响。所以,一个查询中任何其它的属性过滤器将不受影响 – 仅PartitionKey及RowKey受影响。
以下是此问题如何发生的一个例子:插入一个实体并使PartitionKey = “Metric%25” 和RowKey = “Count”的操作将会成功。因为PartitionKey, RowKey和自定义值是请求负载的一部分而并非URL路径部分。现在,当你试图取回这个已经存在的实体之时,Get Entity HTTP URL将会如下所示:
http://foo.table.core.windows.net/Metrics(PartitionKey='Metric%2525',RowKey='Count')
然而由于二次解码的错误,PartitionKey将会在服务器端被翻译成“Metric%”,这与原值不同。在这种情况下,404 Not Found错误将会被返回。
解决方法
如果你尚未在任何实体中使用含“%”的PartitionKey或RowKey,我们建议您做如下两件事:
- 避免在PartitionKey和RowKey中用到“%”,或将其替换为其它字符如“-”。
- 考虑在PartitionKey和RowKey中应用URL 安全64位编码。
注意:请不要将重复为PartitionKey和RowKey值编码作为解决方法,以免与将来Windows Azure Tables含有服务器端修正的发布不兼容。
如果你已经插入了含有“%”的PartitionKey或RowKey的实体,我们建议如下解决方案:
- 对于Get Entity:
- 用Entity Group Transaction并使用一个内部的GET Entity命令。(详见下节示例)
- 在调用Query Entities API试图取回一个单一实体时依赖$Filter变量。尽管此方法不适用于Windows Azure Storage 客户端库或WCF Data Services 客户端库的用户,它适用于对传输协议有控制权的用户。举例来说,对于以上“根本原因”一节中所提到的同一个实体可以考虑如下的查询URL语法:
http://foo.table.core.windows.net/Metrics()?$filter=(PartitionKey%20eq%20'Metric%2525')%20and%20(RowKey%20eq%20'Count')
- 对于Update Entity, Merge Entity, Delete Entity, Insert或Merge Entity,以及Insert或Replace Entity的API,请使用Entity Group Transaction以及你想执行的内部操作。(详见下节示例)
Windows Storage Client库的解决方案示例
假设用户已经插入了含有PartitionKey = “Metric%25” 及 RowKey = “Count”的实体。以下代码展示了如何利用Windows Azure Storage Client库以取出和更新实体。这段代码应用了前文提到的Entity Group Transaction的解决方案。请注意Get Entity和Update Entity操作都被作为批量操作执行。
// 创建表的服务上下文
TableServiceContext tableServiceContext = new TableServiceContext(tableClient.BaseUri.ToString(), tableClient.Credentials);
// 建立单点查询
DataServiceQuery<MetricEntity> getEntityQuery = (DataServiceQuery<MetricEntity>)
from entity in tableServiceContext.CreateQuery<MetricEntity>(customersTableName)
where entity.PartitionKey == "Metric%25" && entity.RowKey == "Count"
select entity;
// 建立entity group transaction并使用内部Get Entity的请求
DataServiceResponse batchResponse = tableServiceContext.ExecuteBatch(getEntityQuery);
// 这是批量操作唯一的应答
QueryOperationResponse response = (QueryOperationResponse) batchResponse.First();
if (response.StatusCode == (int) HttpStatusCode.OK)
{
IEnumerator queryResponse = response.GetEnumerator();
queryResponse.MoveNext();
// 读取这个单独的实体
MetricEntity singleEntity = (MetricEntity)queryResponse.Current;
// 更新实体
singleEntity.MetricValue = 100;
tableServiceContext.UpdateObject(singleEntity);
// 确定使用批量操作选项储存
tableServiceContext.SaveChanges(SaveChangesOptions.Batch);
}
Java Storage Client解决方案代码示例
介于上述问题与服务有关,同样的行为也会在用Storage Client的Java库执行单实体操作时发生。然而,也可以同样应用Entity Group Transaction来解决此问题。最新版本的可以被用于实现前述解决方案的库可以在此找到here。
// 定义批量操作
TableBatchOperation batchOperation = new TableBatchOperation();
// 取回实体
batchOperation.retrieve("Metric%25", "Count", MetricEntity.class);
// 提交一个操作到表服务
tableClient.execute("foo", batchOperation);
更多关于用Java Storage Client处理表格的信息请详见:
http://blogs.msdn.com/b/windowsazurestorage/archive/2012/03/05/windows-azure-storage-client-for-java-tables-deep-dive.aspx
长期修正
我们将把这个修正作为下一个版本更新的一部分进行发布。我们介时将更新此帖以反映其针对的版本信息。
我们对为您带来的不便表示深深道歉!
Jean Ghanem
本文翻译自:http://blogs.msdn.com/b/windowsazurestorage/archive/2012/05/28/partitionkey-or-rowkey-containing-the-percent-character-causes-some-windows-azure-tables-apis-to-fail.aspx
分享到:
相关推荐
POCO属性和字段应使用PartitionKey和RowKey属性之一或两者进行标记,以定义组合表键。 也可以使用Timestamp , ETag , Property和Ignore属性。 流利的映射 流利的映射是同名映射样式,我们可以使用它来替代...
当rowkey顺序递增,且不进行预分区时,可能会出现写热点,所有写操作都集中在最大start-key所在的region,导致资源消耗过大和split次数增多。 为了解决热点问题,一种常用的方法是结合预分区和随机散列。通过在...
"HDFSRowKey.scala"可能涉及将Hadoop的HDFS文件系统与HBase的RowKey结合,可能实现了根据HDFS文件中的数据生成RowKey的方法。这种方式可以利用文件系统中的元数据来创建RowKey,帮助实现数据的有序存储,同时利用...
1. RowKey长度应尽可能短,因为较长的RowKey会导致每个Region的大小不均匀,从而影响查询性能。 2. RowKey应考虑数据分布的均衡性,避免数据热点问题,即某些RegionServer负载过重而其他服务器负载较轻。 3. RowKey...
2. 实体(Entity):实体是表中的数据记录,每个实体都有一个唯一键(PartitionKey和RowKey)。 3. 分区键(PartitionKey):用于将数据分组在同一分区中,同一分区内的数据通常具有相似的访问模式。 4. 行键...
SCIM-服务器-Powershell-Azure功能 Azure功能/ PowerShell上的Scim 2.0到Azure表 入门 在portal.azure.com中创建一个新的功能应用程序。 选择代码和Powershell核心 创建后,打开用于功能应用程序的存储帐户并创建表...
where entity.PartitionKey == "partitionValue" && entity.RowKey == "rowValue" select entity; var result = query.Execute().ToList(); ``` 以上代码首先建立对Table Storage的连接,然后创建一个`...
用户历史订单列表查询rowkey设计技巧 最左前缀原则
在本文中,我们将深入探讨如何使用C#编程语言与Azure Storage Table进行交互。Azure Storage Table是微软云平台Azure提供的一种NoSQL数据存储解决方案,适用于结构化但非模式化的数据存储。它非常适合大规模的数据...
FSharp.Azure.Storage FSharp.Azure.Storage是对标准Microsoft 库的包装,允许... Tabletype Game = { [<PartitionKey>] Developer : string [<RowKey>] Name : string HasMultiplayer : bool } 现在,我们将在inGameTa
RowKey是HBase中的一种二进制码流,可以是任意字符串,最大长度为64kb,但实际应用中一般为10-100bytes,以byte[]方式保存,一般设计成定长。 RowKey设计的重要性体现在以下几个方面: 1. 影响HFile存储效率:...
HBase是Apache软件基金会的Hadoop项目中的一个子项目,它是一个开源的非关系型分布式数据库(NoSQL),是Google Bigtable的开源实现。HBase特别适合于存储大量的稀疏数据,其设计目标是提供水平可扩展的数据存储能力...
partitionKey是一个字符串,它对应于将成为分区键的属性的名称。 rowKey是一个对象。 identifier是一个字符串数组,每个字符串都对应于将构成行键的属性。 format是一个字符串,它定义行键将采用的形状。 转换为表...
例如: $filter=(PartitionKey eq 'Sales') and (RowKey eq '2') 第二好的是范围查询,该查询使用PartitionKey并对一系列RowKey值进行过滤以返回多个实体。 PartitionKey值标识特定的分区,而RowKey值标识该分区中...
HBase RowKey 设计与协处理器运用 HBase 是一个基于 HDFS 的分布式、面向列的 NoSQL 数据库,具有高性能、可靠性和扩展性等特点。本文将详细介绍 HBase 的 RowKey 设计和协处理器运用。 HBase 的介绍 HBase 是一...
本资料主要探讨了HBase中的RowKey(行键)设计以及如何利用它来实现高效的索引策略。下面我们将深入探讨这些关键概念。 **1. HBase的基本架构** HBase是基于Google Bigtable模型设计的,它将数据以表的形式存储,...