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.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" lockKeepAlivePeriod="2000"> <locker> <database-locker lockAcquireSleepInterval="10000"/> </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.
Important
For this to work correctly, give the
leaseHolderId
attribute, found on the lease-database-locker
tag, a unique value. This unique value is used to create a lease lock definition.
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="2000"> <locker> <lease-database-locker lockAcquireSleepInterval="10000" leaseHolderId="broker1"/> </locker> </jdbcPersistenceAdapter> </persistenceAdapter>
The lease database locker supports the common configuration properties described in Table 8.1, “Common Locker Properties”.
Default IOException 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.
In ActiveMQ 5.11
jDBCIOExceptionHandler
is deprecated, however in Red Hat JBoss A-MQ 6.3 it is still recommended and is not deprecated. The LeaseLockerIOExceptionHandler
exception handler is supported as well and it works with any persistence adapter that supports pluggable storage lockers whether or not a locker is in use.
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>