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 the 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 the 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

The Shared File Locker is the default locker for the KahaDB persistence adapter. It locks a file to ensure that only the broker holding the lock (the master) is granted access to the message store. You can configure it like this:

This locker doesn't implement the keepAlive method so there's no point in using lockKeepAlivePeriod settings. Note that as of ActiveMQ 5.9.0 the KahaDB persistence adapter can also use the Lease Database Locker (see below).

Database Locker

The Database Locker is the default locker for the 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:

The Database Locker uses its keepAlive method to ensure the broker still holds the lock. You can set the keep alive period using the lockKeepAlivePeriod property. The default period is 30000 ms. If a broker fails to acquire the lock on the database, it will retry every lockAcquireSleepInterval milliseconds.

This locker opens a JDBC transaction against a database table (activemq_lock) that lasts as long as the broker remains alive. This locks the entire table and prevents another broker from accessing the store. In most cases this will be a fairly long running JDBC transaction which occupies resources on the database over time.

A problem with this locker can occur when the master broker crashes or loses its connection to the database. 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, if the database supports failover, and the connection is dropped in the event of a replica failover, that JDBC transaction will be rolled back. The broker sees this as a failure and both master and slave will again compete for a lock.

Lease Database Locker

The Lease Database Locker solves the master/slave problems of the default Database Locker. It does not open a long running JDBC transaction but lets the master broker acquire a lock that's only valid for a short period. To retain the lock the master broker must periodically extend the lock's lease. The slave broker also checks periodically to see if the lease has expired. The lease can survive a db replica failover. You can configure it like this:

In order for this mechanism to work correctly, each broker in the master/slave pair must have a different brokerName attribute defined on the broker tag or use the lease-database-locker leaseHolderId attribute, as it is this value that is used to reserve a lease.

The lease based lock is acquired by blocking at startup. It is then retained for a period whose duration (in ms) is given by the lockKeepAlivePeriod attribute. To retain the lock the master broker periodically extends its lease by lockAcquireSleepInterval milliseconds each time. In theory, therefore, the master broker is always (lockAcquireSleepInterval - lockKeepAlivePeriod) ahead of the slave broker with regard to the lease. It is imperative that lockAcquireSleepInterval > lockKeepAlivePeriod, to ensure the lease is always current. As of ActiveMQ 5.9.0 a warning message is logged if this condition is not met.

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 greater than zero the local periods will be adjusted by any delta that exceeds maxAllowableDiffFromDBTime.

Icon

It is important to know if the default rules your JDBC driver uses for converting TIME values are JDBC compliant. If you're using MySQL, for example, the driver's JDBC URL should contain useJDBCCompliantTimezoneShift=true to ensure that TIME value conversion is JDBC compliant. If not the locker could report a large time difference when it compares the retrieved lease expiration time against the current system time. Consult your JDBC driver's manual for more details.

As of ActiveMQ 5.9.0 the lease database locker can be used in conjunction with the KahaDB persistence adapter. However, this particular combination requires that the lease database locker element contains a <statements/> child element. In the example below the lockTableName is also configured, although doing so is not mandatory.

To see the complete list of attributes and SQL statements that can be overridden see the Statements class.

 

 

© 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