Chapter 16. Locking
16.1. Locking
Red Hat JBoss Data Grid provides locking mechanisms to prevent dirty reads (where a transaction reads an outdated value before another transaction has applied changes to it) and non-repeatable reads.
16.2. Configure Locking (Remote Client-Server Mode)
In Remote Client-Server mode, locking is configured using the locking
element within the cache tags (for example, invalidation-cache
, distributed-cache
, replicated-cache
or local-cache
).
The default isolation mode for the Remote Client-Server mode configuration is READ_COMMITTED
. If the isolation
attribute is included to explicitly specify an isolation mode, it is ignored, a warning is thrown, and the default value is used instead.
The following is a sample procedure of a basic locking configuration for a default cache in Red Hat JBoss Data Grid’s Remote Client-Server mode.
Configure Locking (Remote Client-Server Mode)
<distributed-cache name="distributedCache"> <locking acquire-timeout="30000" concurrency-level="1000" striping="false" /> <!-- Additional configuration here --> </distributed-cache>
-
The
acquire-timeout
parameter specifies the number of milliseconds after which lock acquisition will time out. -
The
concurrency-level
parameter defines the number of lock stripes used by the LockManager. -
The
striping
parameter specifies whether lock striping will be used for the local cache.
16.3. Configure Locking (Library Mode)
For Library mode, the locking
element and its parameters are set within the default
element found within cache element. An example of this configuration on a local cache is below:
Configure Locking (Library Mode)
<local-cache name="default"> <locking concurrency-level="${VALUE}" isolation="${LEVEL}" acquire-timeout="${TIME}" striping="${TRUE/FALSE}" write-skew="${TRUE/FALSE}" /> </local-cache>
-
The
concurrency-level
parameter specifies the concurrency level for the lock container. Set this value according to the number of concurrent threads interacting with the data grid. -
The
isolation
parameter specifies the cache’s isolation level. Valid isolation levels areREAD_COMMITTED
andREPEATABLE_READ
. For details about isolation levels, see About Isolation Levels. -
The
acquire-timeout
parameter specifies time (in milliseconds) after which a lock acquisition attempt times out. -
The
striping
parameter specifies whether a pool of shared locks are maintained for all entries that require locks. If set toFALSE
, locks are created for each entry in the cache. For details, see About Lock Striping. -
The
write-skew
parameter is only valid if theisolation
is set toREPEATABLE_READ
. If this parameter is set toFALSE
, a disparity between a working entry and the underlying entry at write time results in the working entry overwriting the underlying entry. If the parameter is set toTRUE
, such conflicts (namely write skews) throw an exception. Thewrite-skew
parameter can be only used withOPTIMISTIC
transactions and it requires entry versioning to be enabled, withSIMPLE
versioning scheme.
16.4. Locking Types
16.4.1. About Optimistic Locking
Optimistic locking allows multiple transactions to complete simultaneously by deferring lock acquisition to the transaction prepare time.
Optimistic mode assumes that multiple transactions can complete without conflict. It is ideal where there is little contention between multiple transactions running concurrently, as transactions can commit without waiting for other transaction locks to clear. With write-skew
enabled, transactions in optimistic locking mode roll back if one or more conflicting modifications are made to the data before the transaction completes.
16.4.2. About Pessimistic Locking
Pessimistic locking is also known as eager locking.
Pessimistic locking prevents more than one transaction to modify a value of a key by enforcing cluster-wide locks on each write operation. Locks are only released once the transaction is completed either through committing or being rolled back.
Pessimistic mode is used where a high contention on keys is occurring, resulting in inefficiencies and unexpected roll back operations.
16.4.3. Pessimistic Locking Types
Red Hat JBoss Data Grid includes explicit pessimistic locking and implicit pessimistic locking:
- Explicit Pessimistic Locking, which uses the JBoss Data Grid Lock API to allow cache users to explicitly lock cache keys for the duration of a transaction. The Lock call attempts to obtain locks on specified cache keys across all nodes in a cluster. This attempt either fails or succeeds for all specified cache keys. All locks are released during the commit or rollback phase.
- Implicit Pessimistic Locking ensures that cache keys are locked in the background as they are accessed for modification operations. Using Implicit Pessimistic Locking causes JBoss Data Grid to check and ensure that cache keys are locked locally for each modification operation. Discovering unlocked cache keys causes JBoss Data Grid to request a cluster-wide lock to acquire a lock on the unlocked cache key.
16.4.4. Explicit Pessimistic Locking Example
The following is an example of explicit pessimistic locking that depicts a transaction that runs on one of the cache nodes:
Transaction with Explicit Pessimistic Locking
tx.begin() cache.lock(K) cache.put(K,V5) tx.commit()
-
When the line
cache.lock(K)
executes, a cluster-wide lock is acquired onK
. -
When the line
cache.put(K,V5)
executes, it guarantees success. -
When the line
tx.commit()
executes, the locks held for this process are released.
16.4.5. Implicit Pessimistic Locking Example
An example of implicit pessimistic locking using a transaction that runs on one of the cache nodes is as follows:
Transaction with Implicit Pessimistic locking
tx.begin() cache.put(K,V) cache.put(K2,V2) cache.put(K,V5) tx.commit()
-
When the line
cache.put(K,V)
executes, a cluster-wide lock is acquired onK
. -
When the line
cache.put(K2,V2)
executes, a cluster-wide lock is acquired onK2
. -
When the line
cache.put(K,V5)
executes, the lock acquisition is non operational because a cluster-wide lock forK
has been previously acquired. Theput
operation will still occur. -
When the line
tx.commit()
executes, all locks held for this transaction are released.
16.4.6. Configure Locking Mode (Remote Client-Server Mode)
To configure a locking mode in Red Hat JBoss Data Grid’s Remote Client-Server mode, use the transaction
element as follows:
<transaction locking="{OPTIMISTIC/PESSIMISTIC}" />
16.4.7. Configure Locking Mode (Library Mode)
In Red Hat JBoss Data Grid’s Library mode, the locking mode is set within the transaction
element as follows:
<transaction transaction-manager-lookup="{TransactionManagerLookupClass}" mode="{NONE, BATCH, NON_XA, NON_DURABLE_XA, FULL_XA}" locking="{OPTIMISTIC,PESSIMISTIC}"> </transaction>
Set the locking
value to OPTIMISTIC
or PESSIMISTIC
to configure the locking mode used for the transactional cache.
16.5. Locking Operations
16.5.1. About the LockManager
The LockManager
component is responsible for locking an entry before a write process initiates. The LockManager
uses a LockContainer
to locate, hold and create locks. There are two types of LockContainers
JBoss Data Grid uses internally and their choice is dependent on the useLockStriping
setting. The first type offers support for lock striping while the second type supports one lock per entry.
See Also: Set Up Lock Striping
16.5.2. About Lock Acquisition
Red Hat JBoss Data Grid acquires remote locks lazily by default. The node running a transaction locally acquires the lock while other cluster nodes attempt to lock cache keys that are involved in a two phase prepare/commit phase. JBoss Data Grid can lock cache keys in a pessimistic manner either explicitly or implicitly.
16.5.3. About Concurrency Levels
Concurrency refers to the number of threads simultaneously interacting with the data grid. In Red Hat JBoss Data Grid, concurrency levels refer to the number of concurrent threads used within a lock container.
In JBoss Data Grid, concurrency levels determine the size of each striped lock container. Additionally, concurrency levels tune all related JDK ConcurrentHashMap
based collections, such as those internal to DataContainers
.