분산 캐시용 개체 쿼리 언어

저자: 이크발 칸

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 Reflection을 사용하여 인덱싱된 특성에서 데이터를 추출하고 내부 인덱스를 빌드합니다. 그런 다음 Cache.Search() 또는 Cache.SearchEntries()를 사용하여 캐시를 쿼리하면 NCache 이 인덱스를 사용하여 원하는 개체를 빠르게 찾고 사용자에게 반환합니다.

캐시를 시작하기 전에 객체 속성 인덱싱
그림 1: 캐시를 시작하기 전에 개체 속성 인덱싱

개체 속성에 대한 인덱스를 지정할 때마다 추가, 삽입 및 제거 작업의 처리 시간이 약간 추가됩니다. 그러나 Get 작업은 영향을 받지 않습니다.

다양한 캐싱 토폴로지 쿼리

클라이언트 응용 프로그램의 관점에서 검색 동작은 사용 중인 캐싱 토폴로지에 관계없이 동일하지만 검색의 내부는 토폴로지마다 다릅니다. 예를 들어 복제된 캐시에서 검색을 수행하는 경우 검색은 이 검색을 시작한 캐시 서버에서 완전히 수행됩니다. 전체 캐시를 사용할 수 있기 때문입니다. 다음은 복제된 캐시에서 쿼리를 실행하는 방법입니다.

쿼리가 한 서버에서 로컬로 실행됨
그림 2: 쿼리가 한 서버에서 로컬로 실행됨

그러나 분할 또는 분할된 복제본 캐싱 토폴로지가 있는 경우 모든 데이터가 클러스터의 단일 캐시 노드에 있는 것은 아닙니다. 이 상황에서 쿼리가 시작된 캐시 서버는 쿼리를 클러스터의 다른 모든 서버에 보내고 로컬에서도 실행합니다. 그런 다음 쿼리는 모든 서버에서 병렬로 실행되고 그 결과는 모든 노드에서 이 원래 서버 노드로 반환됩니다. 그런 다음 이 서버 노드는 모든 결과를 결합하고("결합" 수행) 이를 클라이언트에 반환합니다. 아래는 이 모든 것을 보여주는 다이어그램입니다.

쿼리는 모든 서버 노드에서 병렬로 실행됩니다.
그림 3: 모든 서버 노드에서 병렬로 실행되는 쿼리

.NET 어셈블리

In NCache, 인덱싱은 서버 노드에서 수행됩니다. 하지만, NCache 클라이언트 측에서 .NET Reflection을 사용하여 개체 속성 값을 추출하고 서버로 보냅니다. 따라서 개체 정의가 포함된 .NET 어셈블리는 응용 프로그램이 있는 클라이언트 쪽에서만 필요합니다. InProc 모드에서 실행하든 OutProc 모드에서 실행 중이든 어셈블리는 클라이언트 애플리케이션이 액세스할 수 있는 디렉터리에 있어야 합니다.

또한, NCache Java 클라이언트에 대한 개체 쿼리 언어도 지원합니다.

쿼리 언어 구문

NCache OQL(Object Query Language)이라는 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 분산 캐시를 매우 간단하게 쿼리할 수 있습니다. 이것은 캐시를 보다 의미 있는 방식으로 사용하고 캐시에서 항목을 더 쉽게 찾을 수 있게 해주는 강력한 기능입니다. 확인 해봐.


저자: 이크발 칸(Iqbal Khan)이 근무하는 곳 Alachisoft , .NET 및 Java 분산 캐싱, O/R 매핑 및 SharePoint 스토리지 최적화 솔루션을 제공하는 선도적인 소프트웨어 회사입니다. 당신은 그에게 연락할 수 있습니다 이크발@alachisoft.COM.

© 저작권 Alachisoft 2002 - . 판권 소유. NCache 는 Diyatech Corp.의 등록상표입니다.