With 5.7.0 release, we introduced the change on locking strategies for shared storage master/slave topologies. Previously storage locking (and thus master election) was hard-coded directly in the particular store. So KahaDB had only the option to use shared file lock, while JDBC was using database lock.

Now, the storage locking is separated from the store, so you can implement your own locking strategies if necessary (or tune existing ones). Of course, every store has it's own default locker.

Lockers

Every locker must implement Locker interface. So there are a couple of settings you can tune for every locker

Property Name Default Value Description
lockAcquireSleepInterval 10000 Delay interval in milliseconds between lock acquire attempts
failIfLocked false Should the start fail immediately if lock cannot be obtained

Persistence Adapters

Every persistence adapter (or other broker service that wants to use locks) needs to implement Lockable interface. You can use a few settings for every persistence adapter (that supports locking):

Property Name Default Value Description
useLock true can be used to turn off locking if necessary
lockKeepAlivePeriod 0 If bigger than 0, time period (in milliseconds) to keep lock alive

Existing Lockers

Shared File Locker

Shared File Locker is a default locker used by KahaDB. It locks a file to ensure that only single resource is used. You can configure it like this:

<persistenceAdapter>
	<kahaDB directory = "target/activemq-data">
		<locker>
			<shared-file-locker lockAcquireSleepInterval="5000"/>
		</locker>
	</kahaDB>
</persistenceAdapter>

This locker doesn't implement keep alive function so there's no point in using lockKeepAliverPeriod settings

Database Locker

Database Locker is used by default by JDBC persistence adapter. It locks a database table in a transaction to ensure that only single resource is used. You can configure it like this:

<persistenceAdapter>
       <jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" lockKeepAlivePeriod="10000">
          <locker>
            <database-locker lockAcquireSleepInterval="5000"/>
          </locker>
       </jdbcPersistenceAdapter>
    </persistenceAdapter>

Database locker uses keep alive to make sure broker still holds a lock. You can set keep alive period with lockKeepAlivePeriod property. Default value is 30000 (meaning 30 seconds).

The problem with this locker can occur when the master broker lose its connection to the database or crash unexpectedly. The information about the lock remains in the database, until the database responds to the half closed socket connection via a tcp timeout. The database lock expiry requirement can prevent the slave from starting for a period.
In addition, where the database supports failover, and the connection is dropped in the event of a replica failover, the broker sees this as a failure and both master and slave will again compete for a lock.

Lease Database Locker

Lease database locker solves master/slave problem of the default database locker. Master acquires a lock only for a certain period and must extend it's lease from time to time. Slave also checks periodically to see if the lease has expired. The lease can survive a db replica failover. You can configure it like this:

<persistenceAdapter>
	<jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" lockKeepAlivePeriod="5000">
		<locker>
			<lease-database-locker lockAcquireSleepInterval="10000"/>
		</locker>
	</jdbcPersistenceAdapter>
</persistenceAdapter>

The lease based lock is acquired by blocking at start and retained by the keepAlivePeriod. To retain, the lease is extended by the lockAcquireSleepInterval, so in theory the master is always (lockAcquireSleepInterval-lockKeepAlivePeriod) ahead of the slave w.r.t the lease. It is imperative that lockAcquireSleepInterval > lockKeepAlivePeriod, to ensure the lease is always current.
In the simplest case, the clocks between master and slave must be in sync for this solution to work properly. If the clocks cannot be in sync, the locker can use the system time from the database CURRENT TIME and adjust the timeouts in accordance with their local variance from the db system time. If maxAllowableDiffFromDBTime is > 0 the local periods will be adjusted by any delta that exceeds maxAllowableDiffFromDBTime.

© 2004-2011 The Apache Software Foundation.
Apache ActiveMQ, ActiveMQ, Apache, the Apache feather logo, and the Apache ActiveMQ project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.
Graphic Design By Hiram