ASP.NET 웹 애플리케이션, .NET 웹 서비스 애플리케이션 및 기타 .NET 서버 애플리케이션은 속도 저하 없이 극심한 트랜잭션 로드를 처리해야 합니다. 애플리케이션 계층은 선형적으로 확장할 수 있지만 데이터 스토리지와 데이터베이스 계층은 그렇지 못한 경우가 많아 병목 현상이 발생하여 전체 애플리케이션 확장성을 방해합니다.
이러한 문제를 해결하기 위해 다음과 같은 간단한 메모리 내 분산 키-값 저장소가 있습니다. Memcached Redis 이러한 확장성 문제를 해결하기 위해 Unix/Linux 플랫폼에 도입되었습니다. 이는 애플리케이션 계층과 마찬가지로 선형 확장성을 제공하여 데이터베이스 병목 현상을 효과적으로 제거했기 때문에 빠르게 인기를 얻었습니다. 그러나 이러한 문제를 해결하기 위한 첫 번째 시도에서는 이 블로그에서 살펴볼 후속 .NET 분산 캐시만큼 포괄적이지 않았습니다.
키 값 저장소의 제한 사항
그러나 이러한 인기에도 불구하고 이러한 솔루션은 매우 단순하고 기본적이어서 실제 애플리케이션 문제를 해결하지 못했습니다. 그들은 여러 영역에서 심각한 약점을 보였습니다.
- 고가용성 방지
- 오래된 캐시 데이터
- SQL 쿼리를 처리할 수 없음
- 서버측 캐싱 코드 부족(예: Read-through, Write-through, Cache Loader & Refresher 등)
예를 들어, Memcached의 가용성이 너무 낮아 제3자가 이에 대한 고가용성 "수정 기능"을 개발하기 시작했습니다. 불행하게도 기본 아키텍처는 고가용성을 위해 설계되지 않았으므로 이러한 솔루션의 효율성이 제한됩니다. Redis 유사한 가용성 문제에 직면했지만 나중에 장애 조치 지원과 같은 일부 고가용성 기능을 통합하도록 제품을 다시 설계했습니다. 이러한 개선에도 불구하고 두 가지 모두 Memcached Redis 아직 몇 가지 단점이 있습니다. 이는 키-값 저장소에 부족한 필수 기능과 안정성을 제공하기 위해 고급 분산 캐시 솔루션이 개입하는 곳입니다.
.NET 분산 캐시를 2로 사용nd 생성 키-값 저장소
.NET 분산 캐시 NCache, 위에서 언급한 모든 제한 사항을 해결하기 위해 처음부터 설계되었습니다. 2세대 솔루션으로는 NCache 다음과 같은 키-값 저장소의 기능을 뛰어넘습니다. Memcached Redis. 10년 이상 검증된 신뢰성을 바탕으로 NCache 이 블로그에 자세히 설명된 대로 현대의 높은 트랜잭션 요구 사항을 충족하는 데 필요한 고급 기능과 성능을 제공하는 .NET 애플리케이션을 위한 인기 있고 강력한 분산 캐시가 되었습니다.
동적 캐시 클러스터 및 데이터 복제
NCache 클러스터의 모든 캐시 서버에서 모든 CPU 및 메모리 리소스를 풀링하는 자가 치유 동적 캐시 클러스터가 있습니다. 동시에, NCache 다양한 제공 캐싱 토폴로지 데이터 배포 및 복제 전략이 다릅니다. 이를 통해 NCache 가용성을 저하시키지 않고 선형적으로 확장할 수 있습니다. 그리고 캐시 서버가 다운되더라도 캐시 클러스터는 데이터 손실 없이 계속 실행되며, 캐시를 사용하는 모든 애플리케이션도 중단 없이 계속됩니다.
캐시를 최신 상태로 유지
분산 캐시가 사용되는 또 다른 영역 NCache Shine은 데이터를 최신 상태로 유지하고 데이터베이스와 일관성을 유지합니다. 이는 다음과 같은 다양한 기능을 통해 수행됩니다. 만료, 이벤트 기반 SqlDependency, CLR 절차 관계형 데이터베이스 등을 위한 것입니다. 만료는 키-값 저장소처럼 작동하지만 SQL 종속성 수 NCache 관련 데이터에 대한 데이터베이스의 변경 사항과 캐시를 동기화합니다. 그리고, CLR 저장 프로시저 해당 데이터가 변경될 때 SQL Server 데이터베이스에서 캐시를 직접 업데이트할 수 있습니다.
즉, 타사 응용 프로그램이 데이터베이스의 데이터를 변경하더라도 NCache 그에 따라 관련 캐시 데이터를 즉시 업데이트합니다. 응용 프로그램 성능을 향상시키는 읽기 전용 데이터에 비해 모든 관련 응용 프로그램 데이터를 캐싱하는 것이 이점입니다.
SQL 및 LINQ를 사용하여 캐시 쿼리
"캐시를 최신 상태로 유지" 기능을 사용하여 거의 모든 데이터를 캐시할 수 있는 경우 키-값 메커니즘에만 의존하면 데이터 검색이 어려울 수 있습니다. 하지만 속성을 기반으로 데이터를 검색할 수 있다면 다음과 같은 분산 캐시가 필요합니다. NCache 데이터베이스만큼 검색이 쉬워집니다. 이를 위해, NCache 제공 SQL LINQ 쿼리 기능을 통해 데이터 검색을 효율적이고 간단하게 만듭니다.
객체 속성을 기반으로 하는 이러한 쿼리 메커니즘 외에도 다음을 할당할 수 있습니다. 그룹, 태그예산 및 명명된 태그 캐시된 항목을 쿼리에 포함시킵니다. 다음은 UnitPrice를 기준으로 모든 제품을 검색하고 Category 및 Count에 따라 그룹화하는 SQL 쿼리의 예입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
string query = "SELECT Category, COUNT(*) FROM FQN.Product WHERE UnitPrice < ? Group By Category"; // Use QueryCommand for query execution var queryCommand = new QueryCommand(query); queryCommand.Parameters.Add("UnitPrice", 100.0); // Executing QueryCommand through ICacheReader ICacheReader reader = cache.SearchService.ExecuteReader(queryCommand); // Check if result set is not empty if (reader.FieldCount > 0) { while (reader.Read()) { // Get the value of the result set string category = reader.GetValue<string>("Category"); int count = reader.GetValue<int>("COUNT()"); Console.WriteLine($"Category '{category}' has '{count}' affordable products."); } } else { Console.WriteLine($"No category contains affordable products."); } |
서버측 코드
마지막으로 다음과 같은 서버 측 코드는 전체 읽기, 연속 기입, 사용자 지정 종속성예산 및 캐시 로더 및 리프레셔 매우 귀중합니다. 이러한 코드는 사용자가 개발하지만 캐시 클러스터 내의 분산 캐시에 의해 실행되므로 자주 사용되는 논리를 캐싱 계층으로 이동하여 애플리케이션을 단순화할 수 있습니다.
예를 들어, NCache 애플리케이션이 캐시에 없는 데이터를 요청할 때 Read-through 핸들러를 호출합니다. Read-through 핸들러는 데이터를 검색하여 캐시에 로드합니다. 마찬가지로, 연속 읽기와 만료 및 데이터베이스 동기화를 결합하면 캐시된 항목을 캐시에서 제거하는 대신 자동으로 다시 로드할 수 있습니다.
연속 기입은 연속 읽기와 동일한 방식으로 작동하지만 업데이트를 처리합니다. 애플리케이션이 캐시를 업데이트하면 Write-through를 통해 데이터베이스도 업데이트됩니다. 대안적으로, 후기 쓰기 캐시가 동기적으로 업데이트되는 동안 데이터베이스를 비동기적으로 업데이트할 수 있습니다. 마지막으로, 캐시가 시작될 때 캐시 로더가 호출되어 원하는 데이터를 미리 로드할 수 있으므로 자주 액세스하는 정보를 쉽게 사용할 수 있습니다. 다음 코드 샘플은 Read-through 캐싱 공급자를 구성하기 위한 샘플 구현을 제공합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
public class SampleReadThruProvider : IReadThruProvider { private SqlConnection _connection; // Perform tasks like allocating resources or acquiring connections public void Init(IDictionary parameters, string cacheId) { // Create SQL connection and other initializations at the server-side } // Responsible for loading an item from the external data source public ProviderCacheItem LoadFromSource(string key) { // LoadFromDataSource loads data from data source object value = LoadFromDataSource(key); var cacheItem = new ProviderCacheItem(value); return cacheItem; } // Responsible for loading bulk of items from the external data source public IDictionary<string, ProviderCacheItem> LoadFromSource(ICollection<string> keys) { var dictionary = new Dictionary<string, ProviderCacheItem>(); foreach (string key in keys) { // LoadFromDataSource loads data from data source dictionary.Add(key, new ProviderCacheItem(LoadFromDataSource(key))); } return dictionary; return dictionary; } // Adds ProviderDataTypeItem with enumerable data type public ProviderDataTypeItem<IEnumerable> LoadDataTypeFromSource(string key, DistributedDataType dataType) { IEnumerable value = null; ProviderDataTypeItem<IEnumerable> dataTypeItem = null; switch (dataType) { case DistributedDataType.List: value = new List<object>() { LoadFromDataSource(key) }; dataTypeItem = new ProviderDataTypeItem<IEnumerable>(value); break; case DistributedDataType.Dictionary: value = new Dictionary<string, object>() { { key , LoadFromDataSource(key) } }; dataTypeItem = new ProviderDataTypeItem<IEnumerable>(value); break; } return dataTypeItem; } // Perform tasks associated with freeing, releasing, or resetting resources. public void Dispose() { if (_connection != null) { _connection.Close(); } } } |
맺음말
당신이 볼 수 있듯이, NCache오픈 소스 .NET 분산 캐시인 는 다음과 같은 키-값 저장소에 비해 훨씬 더 뛰어난 기능과 성능을 제공합니다. Redis or Memcached. 간의 상세한 비교는 Redis NCache, 만큼 잘 Memcached NCache, 방법을 명확하게 설명합니다. NCache 캐싱 성능과 기능을 향상시켜 복잡하고 트랜잭션이 많은 애플리케이션을 처리하는 데 탁월한 선택입니다.






