Chapter 17. Locking

17.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.

17.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).

Note

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>

  1. The acquire-timeout parameter specifies the number of milliseconds after which lock acquisition will time out.
  2. The concurrency-level parameter defines the number of lock stripes used by the LockManager.
  3. The striping parameter specifies whether lock striping will be used for the local cache.

17.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>

  1. 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.
  2. The isolation parameter specifies the cache’s isolation level. Valid isolation levels are READ_COMMITTED and REPEATABLE_READ. For details about isolation levels, see About Isolation Levels.
  3. The acquire-timeout parameter specifies time (in milliseconds) after which a lock acquisition attempt times out.
  4. The striping parameter specifies whether a pool of shared locks are maintained for all entries that require locks. If set to FALSE, locks are created for each entry in the cache. For details, see About Lock Striping.
  5. The write-skew parameter is only valid if the isolation is set to REPEATABLE_READ. If this parameter is set to FALSE, 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 to TRUE, such conflicts (namely write skews) throw an exception. The write-skew parameter can be only used with OPTIMISTIC transactions and it requires entry versioning to be enabled, with SIMPLE versioning scheme.

17.4. Locking Types

17.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.

17.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.

17.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.

17.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()

  1. When the line cache.lock(K) executes, a cluster-wide lock is acquired on K.
  2. When the line cache.put(K,V5) executes, it guarantees success.
  3. When the line tx.commit() executes, the locks held for this process are released.

17.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()

  1. When the line cache.put(K,V) executes, a cluster-wide lock is acquired on K.
  2. When the line cache.put(K2,V2) executes, a cluster-wide lock is acquired on K2.
  3. When the line cache.put(K,V5) executes, the lock acquisition is non operational because a cluster-wide lock for K has been previously acquired. The put operation will still occur.
  4. When the line tx.commit() executes, all locks held for this transaction are released.

17.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}" />

17.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.

17.5. Locking Operations

17.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

17.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.

17.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.