항목에 대한 배타적 잠금(비관적 잠금)
NCache 캐시된 데이터만 잠그는 비관적 잠금 메커니즘을 제공합니다. 이 메커니즘은 잠금 핸들을 사용하여 항목을 잠그므로 다른 모든 사용자는 해당 캐시 항목에 대한 쓰기 작업을 수행할 수 없습니다. ㅏ LockHandle
Locking API에 의해 반환되는 캐시의 모든 잠긴 항목과 연결됩니다.
주의 사항
이 기능은 다음에서도 사용할 수 있습니다. NCache Professional.
잠긴 항목은 해당 잠금 핸들이 API 수준에서 제공되는 경우에만 가져오거나 업데이트하거나 잠금 해제할 수 있습니다. 그러나 데이터 무결성 문제를 방지하려면 주의해서 이 작업을 수행해야 합니다. 비관적 잠금은 달성하려는 목표가 데이터 일관성인 경우 매우 좋은 접근 방식입니다.
를 사용하여 잠금을 획득하면 LockHandle
, 해제하는 두 가지 메커니즘이 있습니다. 이러한 메커니즘은 모두 아래에 설명되어 있습니다.
시간 기반 잠금 해제: 캐시된 항목을 잠그는 동안 잠금 시간 초과를 지정할 수도 있습니다. 잠금 시간 초과는 시간 초과 간격 동안 잠금을 해제하기 위한 명시적인 호출이 이루어지지 않은 경우 잠금이 자동으로 해제되는 시간 간격입니다. 이렇게 하면 데이터가 무한한 시간 동안 잠기는 것을 방지할 수 있습니다.
강제 잠금 해제: 캐시 항목에 대한 잠금을 획득한 애플리케이션이 갑자기 종료되거나 애플리케이션이 잠긴 데이터에 대한 처리를 완료하는 경우 분산 환경에서 상황이 발생할 수 있습니다. 이러한 상황에서는 해당 애플리케이션이 획득한 모든 잠금을 해제하고 싶을 것입니다. NCache 캐시 아이템 잠금을 강제로 해제하는 Unlock API를 제공합니다.
주의 사항
자원 획득을 최소한의 시간 동안 유지하기 위해 조건이 충족된 후 아이템이 잠금 해제되도록 시간 기반 잠금 메커니즘을 사용하는 것이 좋습니다.
비관적 잠금을 사용하는 경우
앞 장에서 논의한 예를 들어보자. 업데이트 작업을 위해 동일한 인스턴스에서 두 명의 다른 사용자가 동일한 은행 계좌에 액세스하는 경우 충돌이 발생하여 데이터 불일치가 발생할 수 있습니다.
이 시나리오에서 비관적 잠금을 사용하면 한 명의 사용자가 한 번에 계정에 액세스할 수 있습니다. 성공적으로 작동하면 사용자는 항목의 잠금을 해제하고 제어권이 자유롭게 설정됩니다. 이는 이제 두 번째 사용자가 계정에 액세스하여 그에 따라 수정할 수 있음을 의미합니다.
이 접근 방식을 사용하면 데이터가 일관성을 유지하고 충돌이 발생하지 않습니다.
A LockHandle
캐시 전체에서 특정 항목에 액세스할 수 없도록 하기 위해 항목과 연결됩니다.
NCache 잠금 메커니즘을 조작하는 수많은 오버로드뿐만 아니라 잠금만을 호출하는 메서드를 제공합니다.
사전 조건
항목을 명시적으로 잠그기
작업을 수행하기 전에 항목을 명시적으로 잠글 수 있습니다. 이 방법에는 TimeSpan
특정 시간 동안 항목을 잠그려면 그러나 획득한 잠금이 만료되는 것을 원하지 않는 경우 다음을 지정하십시오. TimeSpan.Zero
. 아니오 지정 TimeSpan
무한 시간 동안 항목을 잠급니다.
XNUMXD덴탈의 Lock
이 예에서 사용된 방법은 LockHandle
열쇠로. 싱글이 되도록 해주세요. LockHandle
단일 키와 연결되어 있습니다. 핸들을 재사용하기 전에 잠금 장치를 해제하십시오. 그렇지 않으면 동작의 불일치가 발생할 수 있습니다.
항목이 이미 잠겨 있으면 false 값이 반환되지만 업데이트된 항목을 받게 됩니다. LockHandle
.
경고
최소한의 항목 잠금 TimeSpan
교착 상태나 기아 상태를 피하기 위해.
다음 예제는 LockHandle
그런 다음 키로 항목을 잠급니다. Product:1001
10초 동안 해당 항목이 10초 후에 자동으로 잠금 해제된다는 의미입니다.
// Preconditions: Cache is already connected
// Item is already added in the cache
// Specify the key of the item
string key = $"Product:1001";
//Create a new LockHandle
LockHandle lockHandle = null;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
// Lock the item for a time span of 10 seconds
bool lockAcquired = cache.Lock(key, lockSpan, out lockHandle);
// Verify if the item is locked successfully
if (lockAcquired == true)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
// Precondition: Cache is already connected
// Item is already added in the cache
// Specify the key of the item
String key = "Product:1001";
//Create a new LockHandle
LockHandle lockHandle = new LockHandle();
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
// Lock the item for a time span of 10 seconds
boolean lockAcquired = cache.lock(key, lockSpan, lockHandle);
// Verify if the item is locked successfully
if (lockAcquired == true)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
// This is an async method
// Precondition: Cache is already connected
// Item is already added in the cache
// Specify the key of the item
var key = "Product:1001";
//Create a new LockHandle
var lockHandle = new ncache.LockHandle();
// Specify time span of 10 seconds for which the item remains locked
var lockSpan = new ncache.TimeSpan(None,0,0,10);
// Lock the item for a time span of 10 seconds
var lockAcquired = await this.cache.lock(key, lockSpan, lockHandle);
// Verify if the item is locked successfully
if (lockAcquired == true)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
# Precondtion: Cache is already connected
# Item is already added in the cache
# Specify the key of the item
key = "Product:1001"
# Create a new LockHandle
lock_handle = ncache.LockHandle()
# Specify time span of 10 seconds for which the item remains locked
lock_span = ncache.TimeSpan(None,0,0,10)
# Lock the item for a time span of 10 seconds
lock_acquired = cache.lock(key, lock_span, lock_handle)
# Verify if the item is locked successfully
if lock_acquired:
# Item has been successfully locked
print("Lock successful")
else:
# Key does not exist
# Item is already locked with a different LockHandle
print("Lock failed")
주의 사항
작업이 안전하도록 하려면 에 설명된 대로 응용 프로그램 내에서 잠재적인 예외를 처리하는 것이 좋습니다. 처리 실패.
가져오기 작업 중 항목 잠그기
캐시에서 항목을 검색하는 동안 항목이 잠길 수 있습니다. 즉, 해당 항목을 공개하지 않으면 다른 사람이 해당 항목에 접근할 수 없습니다. 키가 일치하지 않는 경우 null 값이 반환됩니다.
항목이 잠겨 있지 않은 경우 acquirelock
true로 설정하면 LockHandle과 함께 항목을 가져옵니다.
항목이 잠겨 있고 acquirelock
false로 설정되어 있고 올바르지 않거나 새로운 빈 LockHandle을 전달하면 null
값이 반환되지만 이전에 항목을 잠그는 데 사용된 LockHandle을 얻게 됩니다.
항목이 잠겨 있고 acquirelock
이 false로 설정되고 이전에 항목을 잠그는 데 사용된 올바른 LockHandle이 전달되면 값을 얻게 됩니다.
경고
교착 상태나 스레드 부족을 방지하려면 최소 TimeSpan 동안 항목을 잠급니다.
이 예에서는 키와 LockHandle
캐시된 객체를 가져와서 잠그도록 지정되었습니다. 잠금을 획득해야 하는 경우 true를 지정해야 합니다. 여기서 항목은 10초 만료로 잠겨 있습니다. 즉, 해당 항목은 10초 후에 자동으로 잠금 해제됩니다.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
//Create a new LockHandle
LockHandle lockHandle = null;
// Lock the item for a time span of 10 seconds
var result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Verify if the item is locked successfully
if (result != null)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
// Specify the key of the item
String key = "Product:1001";
// Set acquireLock flag as true
boolean acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
//Create a new LockHandle
LockHandle lockHandle = new LockHandle();
// Lock the item for a time span of 10 seconds
Object result = cache.get(key, acquireLock, lockSpan, lockHandle, Object.class);
// Verify if the item is locked successfully
if (result != null)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
// Specify the key of the item
var key = "Product:1001";
// Set acquireLock flag as true
var acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
var lockSpan = new ncache.TimeSpan(None,0,0,10);
//Create a new LockHandle
var lockHandle = new ncache.LockHandle();
// Lock the item for a time span of 10 seconds
//CacheItemVersion set to null and Readthrough Options set to null
var result = await this.cache.getCacheItem(key,null,null, acquireLock, lockSpan, lockHandle);
// Verify if the item is locked successfully
if (result != null)
{
// Item has been successfully locked
}
else
{
// Key does not exist
// Item is already locked with a different LockHandle
}
# Specify the key of the item
key = "Product:1001"
# Set acquireLock flag as true
acquire_lock = True
# Specify time span of 10 seconds for which the item remains locked
lock_span = ncache.TimeSpan(None,0,0,10)
# Create a new LockHandle
lock_handle = ncache.LockHandle()
# Lock the item for a time span of 10 seconds
result = cache.get_cacheitem(key, acquirelock=acquire_lock, locktimeout=lock_span, lockhandle=lock_handle)
# Verify if the item is locked successfully
if result is not None:
# Item has been successfully locked
print("Lock successful")
else:
# Key does not exist
# Item is already locked with a different LockHandle
print("Lock failed")
업데이트 작업으로 잠금 해제
항목을 업데이트하는 동안 다른 사람이 캐시된 데이터를 사용할 수 있도록 잠금을 해제할 수 있습니다. 잠긴 항목을 성공적으로 해제하려면 다음을 지정해야 합니다. LockHandle
처음에는 항목을 잠그는 데 사용됩니다.
XNUMXD덴탈의 LockHandle
항목을 잠그는 데 처음 사용한 것과 동일해야 합니다. 그렇지 않으면 "항목이 잠겼습니다"라는 예외 메시지가 표시됩니다.
If releaseLock
false로 설정되어 있으면 여전히 올바른 값을 전달해야 합니다. Lockhandle
항목을 업데이트합니다.
항목이 잠겨 있지 않으면 LockHandle
와 releaseLock
아무 소용이 없으며 무시됩니다.
다음 예에서는 캐시의 항목을 잠근 다음 LockHandle
. 그런 다음 항목이 업데이트되고 다음을 사용하여 캐시에 다시 삽입됩니다. 끼워 넣다 API.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
// Initialize the lockHandle
LockHandle lockHandle = null;
CacheItem item = cache.GetCacheItem(key, acquireLock, lockSpan, ref lockHandle);
var product = new Product();
product = item.GetValue<Product>();
// Update the unitsinstock for the product
product.UnitsInStock = 200;
bool releaseLock = true;
// Item is already locked with a LockHandle
// Update the item and release the lock as well since releaseLock is set true
// Make sure that the LockHandle matches with the already added LockHandle
cache.Insert(key, item, null, lockHandle, releaseLock);
// Specify the key of the item
String key = "Product:1001";
// Set acquireLock flag as true
boolean acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
// Initialize the lockHandle
LockHandle lockHandle = new LockHandle();
CacheItem item = cache.getCacheItem(key, acquireLock, lockSpan, lockHandle);
// Update the value of item
product = item.getValue(Product.class);
product.setUnitsInStock(200);
boolean releaseLock = true;
// Item is already locked with a LockHandle
// Update the item and release the lock as well since releaseLock is set true
// Make sure that the LockHandle matches with the already added LockHandle
// writeThruOptions set to null
cache.insert(key, item, null, lockHandle,releaseLock);
// This is an async method
// Specify the key of the item
var key = "Product:1001";
// Set acquireLock flag as true
var acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
var lockSpan = new ncache.TimeSpan(None,0,0,10);
// Initialize the lockHandle
var lockHandle = new ncache.LockHandle();
// cacheItemVersion set to null and readThruOptions set to null;
var item = await this.cache.getCacheItem(key,null,null, acquireLock, lockSpan, lockHandle);
// Update the value of item
var product = item.getValue(ncache.JsonDataType.Object);
product.unitsInStock = 200;
var releaseLock = true;
// Item is already locked with a LockHandle
// Update the item and release the lock as well since releaseLock is set true
// Make sure that the LockHandle matches with the already added LockHandle
// writeThruOptions set to null
await this.cache.insert(key, item, null, lockHandle, releaseLock);
# Specify the key of the item
key = "Product:1001"
# Set acquireLock flag as true
acquire_lock = True
# Specify time span of 10 seconds for which the item remains locked
lock_span = ncache.TimeSpan(None,0,0,10)
# Create a new LockHandle
lock_handle = ncache.LockHandle()
# Lock the item for a time span of 10 seconds
item = cache.get_cacheitem(key, acquirelock=acquire_lock, locktimeout=lock_span, lockhandle=lock_handle)
# Update the value of item
product = item.get_value(Product)
product.set_units_in_stock(20)
release_lock = True
# Item is already locked with a LockHandle
# Update the item and release the lock as well since release_lock is set true
# Make sure that the LockHandle matches with the already added LockHandle
cache.insert(key, item, lockhandle=lock_handle, releaselock=release_lock)
명시적으로 잠금 해제
이전에 잠긴 캐시 항목에 대한 잠금을 명시적으로 해제하려면 당신은 LockHandle
처음에는 항목을 잠그는 데 사용됩니다.
경우 LockHandle
저장되지 않은 경우 다른 오버로드를 사용할 수도 있습니다. Unlock
항목의 잠금을 해제하는 데 키만 사용합니다.
주의 사항
유효하지 않은 경우 LockHandle
전달되면 예외는 발생하지 않지만 항목은 잠긴 상태로 유지됩니다.
다음 예는 다음을 사용하여 이미 잠긴 항목을 가져옵니다. LockHandle
그런 다음 사용하여 잠금을 해제합니다. Unlock
API를 사용하는 Lockhandle
전에 저장했습니다.
// Specify the key of the item
string key = $"Product:1001";
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
//Create a new LockHandle
LockHandle lockHandle = null;
Product result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Make sure that the item is already locked and the saved LockHandle is used
// Unlock locked item using saved LockHandle
cache.Unlock(key, lockHandle);
// Specify the key of the item
String key = "Product:1001";
// Set acquireLock flag as true
boolean acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
//Create a new LockHandle
LockHandle lockHandle = new LockHandle();
Object result = cache.get(key, acquireLock, lockSpan, lockHandle, Object.class);
// Make sure that the item is already locked and the saved LockHandle is used
// Unlock locked item using saved LockHandle
cache.unlock(key, lockHandle);
// This is an async method
// Specify the key of the item
var key = "Product:1001";
// Set acquireLock flag as true
var acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
var lockSpan = new ncache.TimeSpan(None,0,0,10);
//Create a new LockHandle
var lockHandle = new ncache.LockHandle();
// cacheItemVersion set to null and readThruOptions set to null;
var result = await this.cache.getCacheItem(key,null,null,acquireLock,lockSpan,lockHandle);
// Make sure that the item is already locked and the saved LockHandle is used
// Unlock locked item using saved LockHandle
await this.cache.unlock(key, lockHandle);
# Specify the key of the item
key = "Product:1001"
# Set acquireLock flag as true
acquire_lock = True
# Specify time span of 10 seconds for which the item remains locked
lock_span = ncache.TimeSpan(None,0,0,10)
# Create a new LockHandle
lock_handle = ncache.LockHandle()
result = cache.get_cacheitem(key, acquirelock=acquire_lock, locktimeout=lock_span, lockhandle=lock_handle)
# Make sure that the item is already locked and the saved LockHandle is used
# Unlock locked item using saved LockHandle
cache.unlock(key, lock_handle)
경고
NCache 다른 오버로드가 있는 경우 잠금을 무시합니다. Get
, Insert
및 Remove
취하거나 사용하지 않는 메소드가 호출됩니다. LockHandle
.
LockHandle로 항목 제거
제거 메소드는 캐시에서 키를 제거하고 제거된 객체를 클라이언트에 반환하는 기본 메소드입니다. 사용자 정의 개체가 캐시에 추가되면 제거 메서드는 Object를 반환합니다.
다음 예에서는 다음을 사용하여 이전에 잠긴 항목을 가져옵니다. LockHandle
그런 다음 저장된 LockHandle
다음을 사용하여 캐시에서 제거 API.
// Specify the key of the item
string key = $"Product:1001";
// Initialize the lockHandle
LockHandle lockHandle = null;
// Set acquireLock flag as true
bool acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = TimeSpan.FromSeconds(10);
// Get the item using the lockHandle
Product result = cache.Get<Product>(key, acquireLock, lockSpan, ref lockHandle);
// Removing locked item using saved lockHandle.
cache.Remove(key, lockHandle);
// Check if item is successfully removed
if (result != null)
{
if (result is Product)
{
Product product = (Product)result;
}
}
// Specify the key of the item
String key = "Product:1001";
// Set acquireLock flag as true
boolean acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
TimeSpan lockSpan = new TimeSpan(0, 0, 10);
//Create a new LockHandle
LockHandle lockHandle = new LockHandle();
Object result = cache.get(key, acquireLock, lockSpan, lockHandle, Object.class);
// Removing locked item using saved lockHandle.
//cacheItemVersion and writeThruOptions set to null
cache.remove(key, lockHandle, null, null, Object.class);
Object test = cache.get(key, Object.class);
// check if item has been removed
if (test != null)
{
//Item has not been removed
}
else
{
// Item has been removed
}
// This is an async method
// Specify the key of the item
var key = "Product:1001";
// Set acquireLock flag as true
var acquireLock = true;
// Specify time span of 10 seconds for which the item remains locked
var lockSpan = new ncache.TimeSpan(None,0,0,10);
//Create a new LockHandle
var lockHandle = new ncache.LockHandle();
// CacheItemVersion and ReadThruOptions set to null
var result = await this.cache.getCacheItem(key,null,null, acquireLock, lockSpan, lockHandle, ncache.JsonDataType.Object);
// Removing locked item using saved lockHandle.
//cacheItemVersion and writeThruOptions set to null
await this.cache.remove(key,ncache.JsonDataType.Object, lockHandle, null, null);
var test = await this.cache.getCacheItem(key);
// check if item has been removed
if (test != null)
{
// Item has not been removed
}
else
{
// Item has been removed
}
# Specify the key of the item
key = "Product:1001"
# Set acquireLock flag as true
acquire_lock = True
# Specify time span of 10 seconds for which the item remains locked
lock_span = ncache.TimeSpan(None,0,0,10)
# Create a new LockHandle
lock_handle = ncache.LockHandle()
result = cache.get_cacheitem(key, acquirelock=acquire_lock, locktimeout=lock_span, lockhandle=lock_handle)
# Removing locked item using saved lock_handle.
cache.remove(key, Product, lockhandle=lock_handle)
test = cache.get_cacheitem(key)
# Check if item has been removed
if test is not None:
# Item has not been removed
print("Remove with lock failed")
else:
# Item has been removed
print("Remove with lock successful")
API 잠금 사용 시 특별 고려 사항
NCache 포함하거나 포함하지 않은 API 세트 제공 LockHandle
캐시 항목을 가져오거나 업데이트합니다. 없는 API LockHandle
아이템 잠금을 무시합니다. 따라서 데이터 조작에는 모든 잠금 API를 사용해야 합니다. 예를 들어, 항목이 잠겨 있고 해당 항목을 사용하지 않는 업데이트 API 호출을 수행하는 경우 LockHandle
입력 매개변수로 사용하면 항목은 잠금 상태에 관계없이 캐시에서 업데이트됩니다.
중대한
잠금 기능을 사용할 때는 다음을 수행하는 API 호출만 사용해야 합니다. LockHandle
매개변수로. 잠금 핸들을 사용하지 않는 API를 사용할 수도 있지만 데이터 무결성에 영향을 주지 않도록 주의해서 사용해야 합니다.
주의 사항
퇴거/만료의 경우, NCache 만료 또는 퇴거로 인해 잠긴 항목이 제거될 수 있음을 의미하는 잠금을 무시합니다.
토폴로지 현명한 동작
. 거울 토폴로지, 모든 잠금 작업에 대해 활성 노드에서 잠금이 획득되며 동일한 LockHandle
그런 다음 패시브 노드에 복제되어 패시브가 활성화되면 항목이 잠긴 상태로 유지됩니다. 마찬가지로 잠금 해제 호출도 패시브 노드에 복제되어 패시브 노드에서 항목의 잠금을 해제합니다.
. 복제 토폴로지에서 클라이언트는 하나의 노드에 연결되며 모든 잠금 작업에 대해 LockHandle
클라이언트 잠금 작업을 수신하는 생성된 다음 동일한 LockHandle
데이터 일관성을 위해 다른 모든 노드에 복제됩니다. 마찬가지로 잠금 해제 작업도 다른 모든 노드에 복제됩니다.
. 파티션 된 토폴로지, LockHandle
항목이 포함된 동일한 노드에 생성되고 존재하며 상태 전송 중에 존재합니다. LockHandle
항목이 다른 노드로 이동하는 경우 정보도 항목과 함께 전송됩니다.
In 파티션-복제본 토폴로지, LockHandle
항목을 포함하는 활성 노드에서 생성되며, LockHandle
그런 다음 데이터 일관성을 위해 그리고 상태 전송 중에 해당 복제본에 복제됩니다. LockHandle
항목이 다른 노드로 이동하는 경우 정보도 항목과 함께 전송됩니다.
. 클라이언트 캐시, 모든 잠금 기반 작업은 클러스터 캐시에서 직접 수행됩니다. LockHandle
클러스터 캐시에 생성되어 저장됩니다. 잠금 관련 정보는 클라이언트 캐시에 유지되지 않습니다.
추가 자료
NCache 항목 잠금에 대한 샘플 애플리케이션을 제공합니다. GitHub의.
도 참조
.그물: Alachisoft.NCache.런타임.캐싱 네임 스페이스.
자바 : COM.alachisoft.ncache.런타임.캐싱 네임 스페이스.
Node.js : 캐시 클래스입니다.
파이썬 : ncache.런타임.캐싱 클래스입니다.