作者:伊克巴尔汗
NCache 允许您在中间层创建一个可扩展的分布式缓存,这样您就可以减少昂贵的数据库访问并大大提高您的应用程序性能。 它还提高了应用程序的可伸缩性,因为您能够在这个高度可伸缩的缓存中找到常用的数据,而不是无法很好地扩展的单个数据库服务器。
您的应用程序通常使用缓存作为 Hashtable,其中所有内容都基于键存储,您必须拥有此键才能获取项目。 这就像拥有一个关系数据库,您只能使用主键来查找数据。 这在许多情况下都可以正常工作,但在现实生活中的复杂应用程序中,您的应用程序通常需要根据主键以外的属性查找数据。 而且,由于您将大量数据保存在缓存中,因此如果您也可以以这种方式搜索缓存,那将非常有用。 NCache 提供正是这样的设施。
在这篇文章中,我将讨论如何 NCache 对象查询有效。
NCache 提供对象查询语言 (OQL) 让您搜索缓存。 您必须进行 API 调用并指定基于此 OQL 的搜索,以便从缓存中获取对象集合。 为了查询缓存,您需要在 .NET 应用程序中使用以下内容。
public class Program
{
public static void Main(string[] args)
{
NCache.InitializeCache("myReplicatedCache");
String query = "SELECT NCacheQuerySample.Business.Product WHERE this.ProductID > 100";
// Fetch the keys matching this search criteria
ICollection keys = NCache.Cache.Search(query);
if (keys.Count > 0)
{
IEnumerator ie = keys.GetEnumerator();
while (ie.MoveNext())
{
String key = (String)ie.Current;
Product prod = (Product)NCache.Cache.Get(key);
HandleProduct(prod);
Console.WriteLine("ProductID: {0}", prod.ProductID);
}
}
NCache.Cache.Dispose();
}
}
上面的代码搜索缓存并返回一个键集合。 然后,它遍历所有返回的键,并从缓存中单独获取相应的缓存项。 这种方法的好处是查询不会自动返回大量数据,而是只返回键。 然后,客户端应用程序可以确定它想要获取哪些密钥。 这种方法的缺点是,如果您无论如何都要从缓存中获取大部分项目,那么您最终会多次访问缓存。 而且,如果缓存是分布式的,这最终可能会变得昂贵。 如果是这种情况,那么您可以进行搜索,将键和项目一起返回。
正如您已经看到的,一个简单的 Cache.Search(...) 返回一个键集合。 但是,如果您打算获取与这些键关联的所有或大部分缓存项,则 Cache.Search(...) 不是搜索缓存的一种非常有效的方法。 原因是您将首先拨打电话进行搜索。 然后,您将进行多次调用以获取与每个键关联的项目。 这可能成为非常昂贵的操作。 在这些情况下,最好在一次调用中获取所有键和项目。 下面是这样做的示例。
public class Program
{
public static void Main(string[] args)
{
NCache.InitializeCache("myReplicatedCache");
String query = "SELECT NCacheQuerySample.Business.Product WHERE this.ProductID > 100";
// Fetch the keys matching this search criteria
IDictionary dict = NCache.Cache.SearchEntries(query);
if (dict.Count > 0)
{
IDictionaryEnumerator ide = dict.GetEnumerator();
while (ide.MoveNext())
{
String key = (String)ide.Key;
Product prod = (Product)ide.Value;
HandleProduct(prod);
Console.WriteLine("Key = {0}, ProductID: {1}",
key, prod.ProductID);
}
}
NCache.Cache.Dispose();
}
}
上面的代码搜索缓存并返回一个包含键和值的字典。 这样,基于搜索条件的所有数据都可以在一次调用中获取 NCache. 这比从缓存中获取所有数据的效率更高 Cache.Search()
.
请注意: NCache 要求对所有可搜索的属性进行索引。 这是因为没有索引, NCache 必须遍历整个缓存才能找到用户正在寻找的项目。 而且,这是一项非常昂贵的操作,可能会减慢整个缓存并撤消人们为什么会这样做的主要原因 NCache,即提高其应用程序性能和可扩展性。
NCache 提供自己的索引机制。 您可以识别 .NET 程序集中要索引的对象。 然后,当您将数据添加到 NCache,它会检查您是否正在添加这些对象。 而且,如果您是,那么它使用 .NET 反射从索引属性中提取数据并构建其内部索引。 然后,当您使用 Cache.Search() 或 Cache.SearchEntries() 查询缓存时, NCache 使用这些索引快速找到所需的对象并将它们返回给您。
请注意,每当您在对象属性上指定索引时,都会增加一点点添加、插入和删除操作的处理时间。 但是,Get 操作不受影响。
尽管无论您使用何种缓存拓扑,从客户端应用程序的角度来看,搜索行为都是相同的,但搜索的内部结构因拓扑而异。 例如,如果您正在对复制的缓存进行搜索,则您的搜索将完全在您发起此搜索的缓存服务器上进行。 这是因为整个缓存都在那里可用。 以下是在复制缓存中运行查询的方式。
但是,如果您具有分区或分区副本缓存拓扑,则并非所有数据都驻留在集群中的单个缓存节点上。 在这种情况下,发起查询的缓存服务器将查询发送到集群中的所有其他服务器,并在本地运行。 然后,该查询在所有服务器中并行运行,其结果从所有节点返回到该原始服务器节点。 该服务器节点然后组合所有结果(执行“联合”)并将它们返回给客户端。 下面是显示所有这些的图表。
In NCache,索引是在服务器节点上完成的。 然而, NCache 在客户端使用 .NET Reflection 来提取对象属性的值并将它们发送到服务器。 因此,包含对象定义的 .NET 程序集只需要在应用程序所在的客户端上。 无论您是在 InProc 还是 OutProc 模式下运行,您的程序集都需要位于您的客户端应用程序可以访问它们的目录中。
此外, NCache 还支持 Java 客户端的对象查询语言。
NCache 支持称为对象查询语言 (OQL) 的类 SQL 语言。 该语言具有以下语法 NCache.
SELECT NCacheQuerySample.Business.Product WHERE this.ProductID > 100;
SELECT NCacheQuerySample.Business.Product WHERE (this.ProductID != 100 AND this.ProductID <= 200);
SELECT NCacheQuerySample.Business.Product WHERE (this.ProductID == 150 OR this.ProductID == 160);
SELECT NCacheQuerySample.Business.Product WHERE this.ProductID IN (1, 4, 7, 10);
SELECT NCacheQuerySample.Business.Product WHERE this.ProductID NOT IN (1, 4, 7, 10);
SELECT NCacheQuerySample.Business.Employee WHERE this.HiringDate > DateTime.now;
SELECT NCacheQuerySample.Business.Employee WHERE this.HiringDate > DateTime ('01/01/2007');
SELECT NCacheQuerySample.Business.Employee WHERE this.Hired = true;
您可以使用 AND 和 OR 以及使用嵌套括号将多个表达式组合在一起。 完整的查询语言语法如下所示。
<Query> ::= SELECT <ObjectType>
| SELECT <ObjectType> WHERE <Expression>
<Expression> ::= <OrExpr>
<OrExpr> ::= <OrExpr> 'OR' <AndExpr>
| <AndExpr>
<AndExpr> ::= <AndExpr> 'AND' <UnaryExpr>
| <UnaryExpr>
<UnaryExpr> ::= 'NOT' <CompareExpr>
| <CompareExpr>
<CompareExpr> ::= <Atrrib> '=' <Value>
| <Atrrib> '!=' <Value>
| <Atrrib> '==' <Value>
| <Atrrib> '<>' <Value>
| <Atrrib> '<' <Value>
| <Atrrib> '>' <Value>
| <Atrrib> '<=' <Value>
| <Atrrib> '>=' <Value>
| <Atrrib> 'IN' <InList>
| <Atrrib> 'NOT' 'IN' <InList>
| '(' <Expression> ')'
<Atrrib> ::= <ObjectValue>
<Value> ::= '-' <NumLiteral>
| <NumLiteral>
| <StrLiteral>
| 'true'
| 'false'
| <Date>
<Date> ::= 'DateTime' '.' 'now'
| 'DateTime' '(' StringLiteral ')'
<StrLiteral> ::= StringLiteral
| 'null'
<NumLiteral> ::= IntegerLiteral
| RealLiteral
<ObjectType> ::= '*'
| <Property>
<Property> ::= <Property> '.' Identifier
| Identifier
<ObjectValue> ::= Keyword '.' Identifier
<InList> ::= '(' <ListType> ')'
<ListType> ::= <NumLiteralList>
| <StrLiteralList>
| <DateList>
<NumLiteralList> ::= <NumLiteral> ',' <NumLiteralList>
| <NumLiteral>
<StrLiteralList> ::= <StrLiteral> ',' <StrLiteralList>
| <StrLiteral>
<DateList> ::= <Date> ',' <DateList>
| <Date>
如您所见, NCache 使得查询分布式缓存变得非常简单。 这是一项强大的功能,可让您以更有意义的方式使用缓存并更轻松地在其中查找内容。 看看这个。
作者: 伊克巴尔·汗为 Alachisoft ,一家领先的软件公司,提供 .NET 和 Java 分布式缓存、O/R 映射和 SharePoint 存储优化解决方案。 你可以联系他 伊克巴尔@alachisoft .