캐시 항목 버전 관리를 통한 잠금(낙관적 잠금)
DaVinci에는 비관적 잠금 매우 유용한 접근 방식이지만 사용에 제한이 있으며 최소한 하나의 작업을 완전히 수행하지 않으면 항목을 사용할 수 없습니다. 이는 해당 항목에 대해 하나의 작업이 완전히 수행될 때까지 해당 항목이 잠긴 상태로 유지됨을 의미합니다. 항목이 오랫동안 잠겨 있으면 스레드 부족이 발생할 수 있습니다.
주의 사항
이 기능은 다음에서도 사용할 수 있습니다. NCache Professional.
낙관적 잠금이 유용한 곳은 다음과 같습니다. NCache 캐시 항목 버전 관리를 사용합니다. CacheItemVersion
모든 캐시 항목과 관련된 속성입니다. 캐시된 항목의 버전을 나타내는 숫자 값으로, 항목이 업데이트될 때마다 XNUMX씩 증가합니다. 이 속성을 사용하면 항목에 변경 사항이 발생하는지 여부를 추적할 수 있습니다. 캐시에서 항목을 가져올 때 캐시에 있는 항목의 현재 버전도 가져옵니다.
읽기 집약적인 애플리케이션의 경우 비관적 잠금보다 낙관적 잠금이 선호됩니다.
낙관적 잠금을 사용하는 경우
이전 예에서는 두 명의 사용자가 동시에 사용하는 단일 은행 계좌가 있었습니다. 사용자 중 한 명이 은행 계좌에 예금 거래를 수행하기 위해 잠금을 획득했다고 가정해 보겠습니다. User2는 User1이 출금 거래를 할 수 있도록 잠금을 해제하기를 기다리고 있습니다. User1이 잠금을 해제하지 않고 네트워크 연결 문제로 인해 불안정한 상태로 전환된다는 점을 고려하세요. User2는 연결 문제에 대한 지식 없이 잠금이 해제될 때까지 계속 기다리므로 첫 번째 사용자가 잠금을 해제할 때까지 기아 상태가 됩니다.
이런 종류의 문제를 방지하려면 Optimistic Locking이 유용한 솔루션입니다. 이러한 종류의 잠금을 사용하면 User1이 계정을 업데이트하려는 경우 계정을 잠그지 않고 업데이트할 수 있으며 이에 따라 항목 버전이 업데이트됩니다. 이제 User2가 데이터를 업데이트하려고 하면 항목 버전을 기반으로 업데이트된 버전을 받게 되며 이를 통해 데이터 무결성 문제가 발생하지 않도록 할 수 있습니다. 사용자가 이전 항목 버전으로 데이터를 작업하는 경우 오래된 항목 버전이 있다는 이유로 작업이 실패합니다.
CacheItemVersion
다음을 사용하여 애플리케이션 개발에 추가적인 차원을 추가합니다. NCache. 낙관적 동시성은 다음을 통해 애플리케이션에서 달성될 수 있습니다. NCache 항목 버전 관리.
캐시에 항목이 추가되면 캐시 항목 버전이 캐시 클라이언트로 반환됩니다. 이 값은 특정 데이터에 대해 수행된 업데이트 수를 나타냅니다. 업데이트할 때마다 아이템 버전의 값이 증가합니다.
사전 조건
항목 버전으로 항목 검색 및 업데이트
An 추가 연산은 CacheItemVersion
. 항목이 처음으로 추가되면 해당 항목 생성의 TimeStamp가 포함된 긴 값이 반환됩니다. 이 버전은 나중에 이 키에 대한 작업을 수행할 때 "1"씩 증가합니다.
낙관적 잠금은 사용자가 항상 캐시에서 항목의 가장 업데이트된 복사본을 얻도록 합니다. 사용자가 오래된 버전에서 계속 기능을 수행하는 경우, NCache 사용자가 캐시에서 업데이트된 항목을 가져오도록 예외를 throw합니다.
아래 예에서 캐시는 여러 애플리케이션에서 사용됩니다. 캐시에는 제품 데이터가 포함되어 있습니다. ㅏ CacheItem
캐시에 추가됩니다. 두 응용 프로그램 모두 현재 버전(예: 버전)으로 항목을 가져옵니다. Application1은 다음을 수정합니다. 상품명 그런 다음 항목을 캐시에 다시 삽입하면 항목의 항목 버전이 새 버전으로 업데이트됩니다. 애플리케이션 2에는 여전히 해당 버전의 항목이 있습니다. Application2가 재고에 있는 항목의 단위를 업데이트하고 항목을 캐시에 다시 삽입하면 삽입이 실패합니다. Application2는 작업을 수행하기 위해 업데이트된 버전을 가져와야 합니다. CacheItem
.
주의 사항
둘 다 사용하여 캐시에 항목을 추가할 수 있습니다. 추가 or 끼워 넣다 방법.
- XNUMXD덴탈의
Add
메서드는 캐시에 새 항목을 추가하고 처음으로 항목 버전을 저장합니다.
- XNUMXD덴탈의
Insert
메서드는 항목이 아직 없는 경우 캐시에 항목을 추가하는 반면 기존 시간 값을 덮어쓰고 항목 버전을 업데이트합니다.
다음 코드 섹션에서는 애플리케이션에서 수행하는 작업을 설명합니다.
// Precondition: Cache is already connected
// An item is added in the cache with itemVersion
// Specify the key of the cacheItem
string key = "Product:1001";
// Initialize the cacheItemVersion
CacheItemVersion version = null;
// Get the cacheItem previously added in the cache with the version
CacheItem cacheItem = cache.GetCacheItem(key, ref version);
// If result is not null
if (cacheitem != null)
{
// CacheItem is retrieved successfully with the version
// If result is Product type
var prod = new Product();
prod = cacheItem.GetValue<Product>();
prod.UnitsInStock++;
// Create a new cacheItem with updated value
var updateItem = new CacheItem(prod);
//Set the itemversion. This version will be used to compare the
// item version of cached item
updateItem.Version = version;
cache.Insert(key, updateItem);
// If it matches, the insert will be successful, otherwise it will fail
}
else
{
// Item could not be retrieved due to outdated CacheItemVersion
}
// Precondition: Cache is already connected
// An item is added in the cache with itemVersion
// Specify the key of the cacheItem
String key = "Product:1001";
// Initialize the cacheItemVersion
CacheItemVersion version = new CacheItemVersion();
// readThruOptions set to null
CacheItem cacheItem = cache.getCacheItem(key, version, null);
// If result is not null
if (cacheItem != null)
{
var prod = new Product();
prod = cacheItem.getValue(Product.Class);
prod.unitsInStock++;
// Update the retrieved cacheitem according to requirement
// Create a new cacheItem with updated value
CacheItem updatedItem = new CacheItem(prod);
// Set the itemversion. This version will be used to compare the
// item version of cached item
updatedItem.setCacheItemVersion(version);
cache.insert(key, updatedItem);
// If it matches, the insert will be successful, otherwise it will fail
}
// This is an async method
// Precondition: Cache is already connected
// An item is added in the cache with itemVersion
// Specify the key of the cacheItem
var key = "Product:1001";
// Initialize the cacheItemVersion
var version = new ncache.CacheItemVersion();
// readThruOptions set to null
var cacheItem = await this.cache.getCacheItem(key, null, version);
// If result is not null
if (cacheItem != null)
{
var prod = new Product();
prod = cacheItem.getValue(ncache.JsonDataType.Object);
prod.unitsInStock++;
// Update the retrieved cacheitem according to requirement
// Create a new cacheItem with updated value
// You also need to specify the FQN(Fully Qualified Name) of the class
var updatedItem = new ncache.CacheItem(prod,"FQN.Product");
// Set the itemversion. This version will be used to compare the
// item version of cached item
updatedItem.setCacheItemVersion(version);
await this.cache.insert(key, updatedItem);
// If it matches, the insert will be successful, otherwise it will fail
}
# Precondition: Cache is already connected
# An item is added in the cache with ItemVersion
# Specify the key of the cacheItem
key = "Product:1001"
# Initialize the cacheItemVersion
version = ncache.CacheItemVersion(0)
cache_item = cache.get_cacheitem(key, cacheitemversion=version)
# If result is not None
if cache_item is not None:
prod = cache_item.get_value(Product)
prod.set_units_in_stock(20)
# Update the retrieved cacheitem according to requirement
# Create a new CacheItem with updated value
updated_item = ncache.CacheItem(prod)
# Set the item_version. This version will be used to compare the
# item version of cached item
updated_item.set_cache_item_version(version)
cache.insert(key, updated_item)
# If it matches, the insert will be successful, otherwise it will fail
주의 사항
작업이 안전하도록 하려면 에 설명된 대로 응용 프로그램 내에서 잠재적인 예외를 처리하는 것이 좋습니다. 처리 실패.
캐시에 최신 버전이 있는 경우 항목 검색
XNUMXD덴탈의 GetIfNewer
캐시에서 최신 버전을 사용할 수 있는 경우 메서드를 사용하여 기존 항목을 가져올 수 있습니다. 현재 버전을 메서드 호출의 인수로 지정하면 캐시는 적절한 결과를 반환합니다.
지정된 버전이 캐시에 있는 버전보다 낮은 경우에만 메서드가 새 항목을 반환합니다. null로 반환됩니다.
다음 예는 키를 사용하여 캐시에 항목을 추가합니다. Product:1001
항목 버전을 입력한 다음 최신 버전이 있으면 검색합니다. GetIfNewer
캐시 항목 버전을 사용하여 항목을 가져오는 메서드입니다.
// Get updated product from database against given product ID
Product product = FetchProductByProductID(1001);
// Generate a unique key for this item
string key = $"Product:{product.ProductID}";
// Create a new CacheItem
var item = new CacheItem(product);
// Add CacheItem to cache with new itemversion
CacheItemVersion version = cache.Insert(key, item);
// Get object from cache
var result = cache.GetIfNewer<Product>(key, ref version);
// Check if updated item is available
if (result != null)
{
// An item with newer version is available
if (result is Product)
{
// Perform operations according to business logic
}
}
else
{
// No new itemVersion is available
}
// Pre-condition: Cache is already connected
// Get updated product from database against given product ID
Product product = fetchProductByProductID(1001);
// Generate a unique key for this item
String key = "Product:" + product.getProductID();
// Create a new CacheItem
CacheItem item = new CacheItem(product);
// Add CacheItem to cache with new itemversion
CacheItemVersion version = cache.insert(key, item);
// Get object from cache
Object result = cache.getIfNewer(key,version,Object.class);
// Check if updated item is available
if (result != null)
{
// Perform operations according to business logic
}
else
{
// No new itemVersion is available
}
// This is an async method
// Pre-condition: Cache is already connected
// Get updated product from database against given product ID
var product = this.fetchProductByProductID(1001);
// Generate a unique key for this item
var key = "Product:" + product.getProductID();
// Create a new CacheItem
// You also need to specifyt the FQN(Fully Qualified Name) of the class
var item = new ncache.CacheItem(product,"FQN.Product");
// Add CacheItem to cache with new itemversion
var version = await this.cache.insert(key, item);
// Get object from cache
var result = await this.cache.getIfNewer(key, ncache.JsonDataType.Object, version);
// Check if updated item is available
if (result != null)
{
// Perform operations according to business logic
}
else
{
// No new itemVersion is available
}
# Pre-condition: Cache is already connected
# Get updated product from database against given product ID
product = fetch_product_from_db(1001)
# Generate a unique key for this item
key = "Product:" + product.get_product_id()
# Create a new CacheItem
item = ncache.CacheItem(product)
# Add CacheItem to cache with new itemversion
version = cache.insert(key, item)
# Get object from cache
result = cache.get_if_newer(key, cacheitemversion=version, objtype=Product)
# Check if updated item is available
if result is not None:
# Perform operations according to business logic
print("New version is available")
else:
# No new ItemVersion is available
print("New version is not available")
항목 버전이 있는 항목 제거
다음의 오버로드를 사용하여 캐시에서 항목을 제거할 수 있습니다. 제거, 항목 버전을 기반으로 합니다. 그러나 항목 버전이 캐시에 있는 것과 다른 경우 이를 지정하는 예외가 발생합니다.
다음 예는 다음을 사용하여 항목 버전을 지정하여 캐시에서 항목을 제거하는 방법을 보여줍니다. 제거 방법.
// Get updated product from database against given product ID
Product product = FetchProductByProductID(1001);
// Cache key remains the same for this product
string key = $"Product:{product.ProductID}";
// Create a new CacheItem
var item = new CacheItem(product);
// Insert CacheItem to cache with new itemversion
CacheItemVersion version = cache.Insert(key, item);
// Remove the item from the cache using the itemVersion
cache.Remove(key, null, version);
// Pre-condition: Cache is already connected
// Get updated product from database against given product ID
Product product = fetchProductByProductID(1001);
// Cache key remains the same for this product
String key = "Product:" + product.getProductID();
// Create a new CacheItem
CacheItem item = new CacheItem(product);
// Add CacheItem to cache with new itemversion
CacheItemVersion version = cache.insert(key, item);
// Remove the item from the cache using the itemVersion
//lockHandle and writeThruOptions set to null
cache.remove(key,null,version,null,Object.class);
Object value = cache.get(key,Object.class);
// Checking if item still exists in cache or not
if(value == null)
{
// Item has been removed from the cache
}
else
{
// Item is still in Cache
}
// Pre-condition: Cache is already connected
// Get updated product from database against given product ID
var product = this.fetchProductByProductID(1001);
// Cache key remains the same for this product
var key = "Product:" + product.getProductID();
// Create a new CacheItem
// You also need to specify the FQN(Fully Qualified Name) of the class
var item = new ncache.CacheItem(product,"FQN.Product");
// Add CacheItem to cache with new itemversion
var version = await this.cache.insert(key, item);
// Remove the item from the cache using the itemVersion
// lockHandle and writeThruOptions set to null
await this.cache.remove(key, ncache.JsonDataType.Object, null, version, null);
var value = await this.cache.get(key, ncache.JsonDataType.Object);
if (value == null)
{
// Item has been removed from cache
}
else
{
// Item is still in cache
}
# Pre-condition: Cache is already connected
# Get updated product from database against given product ID
product = fetch_product_from_db(1001)
# Cache key remains the same for this product
key = "Product:" + product.get_product_id()
# Create a new CacheItem
item = ncache.CacheItem(product)
# Add CacheItem to cache with new itemversion
version = cache.insert(key, item)
# Remove the item from the cache using the ItemVersion
cache.remove(key, version=version, objtype=Product)
value = cache.get(key, Product)
if value is None:
# Item has been removed from cache
print("Remove successful")
else:
# Item is still in cache
print("Remove failed")
토폴로지 현명한 동작
. 거울 토폴로지에서는 항목이 추가되거나 업데이트되면 해당 버전이 능동 노드에서 생성되고 동일한 버전이 항목과 함께 수동 노드에 복제되므로 활성 노드가 패시브가 되어도 항목 버전은 동일하게 유지됩니다.
. 복제 토폴로지 클라이언트는 하나의 노드에 연결되고 클라이언트 업데이트/추가 작업을 수신하는 노드에서 항목 버전이 생성된 다음, 데이터 일관성을 위해 항목과 함께 동일한 항목 버전이 다른 모든 노드에 복제됩니다.
. 파티션 된 토폴로지에서는 항목 버전이 생성되어 항목이 포함된 동일한 노드에 존재하며, 상태 전송 중에 항목이 다른 노드로 이동하는 경우 버전도 항목과 함께 전송됩니다.
. 파티션-복제본 토폴로지, 버전은 항목을 포함하는 활성 노드에서 생성되고 항목과 동일한 버전은 데이터 일관성을 위해 복제본에 복제되며 상태 전송 중에 항목이 다른 항목으로 이동하는 경우 버전도 항목과 함께 전송됩니다. 마디.
. 클라이언트 캐시, 모든 버전 관련 정보는 클러스터 캐시에 유지되며, 버전 관련 API가 호출될 때마다 사용자는 클러스터 캐시에서 해당 버전을 가져옵니다.
추가 자료
NCache 항목 잠금에 대한 샘플 애플리케이션을 제공합니다. GitHub의.
도 참조
.그물: Alachisoft.NCache.런타임.캐싱 네임 스페이스.
자바 : COM.alachisoft.ncache.런타임.캐싱 네임 스페이스.
Node.js : 캐시 클래스입니다.
파이썬 : ncache.런타임.캐싱 클래스입니다.