8.2. Using the Provided Lockers

Red Hat JBoss A-MQ includes three standard locker implementations:
  • shared file locker—used by file-based message stores like KahaDB and LevelDB
  • database locker—used as the default for JDBC message stores
  • lease database locker—used as an alternative locker for JDBC message stores in scenarios where brokers have inconsistent connections to the message store

8.2.1. Shared File Locker

Overview

The shared file locker is used by file-based message stores to ensure that only one broker can modify the files used by the message store.

Configuration

As shown in Example 8.2, “Configuring a Shared File Locker”, the shared file locker is configured using the shared-file-locker element.

Example 8.2. Configuring a Shared File Locker

<persistenceAdapter>
  <kahaDB directory = "target/activemq-data">
    <locker>
      <shared-file-locker lockAcquireSleepInterval="5000"/>
    </locker>
  </kahaDB>
</persistenceAdapter>
The shared file locker supports the common configuration properties described in Table 8.1, “Common Locker Properties”.

8.2.2. Database Locker

Overview

The database locker is the default locker for all JDBC persistence adapters. It locks a database table in a transaction to ensure that only one broker can modify the message store.
The database locker does not perform well in two scenarios:
  • intermittent database connectivity
  • database failover

Configuration

As shown in Example 8.3, “Configuring a Database Locker”, it is configured using the database-locker element.

Example 8.3. Configuring a Database Locker

<persistenceAdapter>
  <jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds">
    <locker>
      <database-locker lockAcquireSleepInterval="5000"/>
    </locker>
  </jdbcPersistenceAdapter>
</persistenceAdapter>
The database locker supports the common configuration properties described in Table 8.1, “Common Locker Properties”.

Intermittent database connectivity

When the master broker loses its connection to the database, or crashes unexpectedly, the information about the lock remains in the database until the database responds to the half-closed socket connection via a TCP timeout. This can prevent the slave from starting for a period of time.

Database failover

When the database used for the message store supports failover issues can arise. When the database connection is dropped in the event of a replica failover, the brokers see this as a database failure and all of the brokers in the master/slave group will begin competing for the lock. This restarts the master election process and can cause the group to failover to a new master. For more information see section "Shared JDBC Master/Slave" in "Fault Tolerant Messaging".

8.2.3. Lease Database Locker

Overview

The lease database locker is designed to overcome the shortcomings of the default database locker by forcing the lock holder to periodically renew the lock. When the lock is first acquired the broker holds it for the period specified in the persistence adapter's lockKeepAlivePeriod attribute. After the initial period, the lock is renewed for the period specified by the locker's lockAcquireSleepInterval attribute.
When all of broker's system clocks are properly synchronized, the master broker will always renew the lease before any of the slaves in the group can steal it. In the event of a master's failure, the lock will automatically expire within the configured amount of time and one of the slave's in the group will be able to acquire it.

Configuration

As shown in Example 8.4, “Configuring a Lease Database Locker”, it is configured using the lease-database-locker element.

Example 8.4. Configuring a Lease Database Locker

<ioExceptionHandler>
  <jDBCIOExceptionHandler/>
</ioExceptionHandler>

<persistenceAdapter>
  <jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" lockKeepAlivePeriod="5000">
    <locker>
      <lease-database-locker lockAcquireSleepInterval="10000"/>
    </locker>
  </jdbcPersistenceAdapter>
</persistenceAdapter>
The lease database locker supports the common configuration properties described in Table 8.1, “Common Locker Properties”.

jDBCIOExceptionHandler exception handler

In order to cope with reconnection to the JDBC database, it is essential to enable a jDBCIOExceptionHandler exception handler to the configuration. The jDBCIOExceptionHandler will pause and resume the transport connectors on any I/O exception related to database access.

Dealing with unsynchronized system clocks

The lease database locker relies on each broker's system clock to enure the proper timing of lease expiration and lock requests. When all of the system clocks are synchronized, the timing works. Once the system clocks start drifting apart, the timing can be thrown off and a slave broker could possibly steal the lock from the group's master.
To avoid this problem the locker can make adjustments based on the database server's current time setting. This feature is controlled by setting the locker's maxAllowableDiffFromDBTime to specify the number of milliseconds by which a broker's system clock can differ from the database's before the locker automatically adds an adjustment. The default setting is zero which deactivates the adjustments.
Example 8.5, “Configuring a Lease Database Locker to Adjust for Non-synchronized System Clocks” shows configuration for making adjustments when a broker's clock differs from the database by one second.

Example 8.5. Configuring a Lease Database Locker to Adjust for Non-synchronized System Clocks

<ioExceptionHandler>
  <jDBCIOExceptionHandler/>
</ioExceptionHandler>

<persistenceAdapter>
  <jdbcPersistenceAdapter ... >
    <locker>
      <lease-database-locker maxAllowableDiffFromDBTime="1000"/>
    </locker>
  </jdbcPersistenceAdapter>
</persistenceAdapter>