INT-4048: Add JdbcLockRegistry support

JIRA: https://jira.spring.io/browse/INT-4048

The semantics of the locks are the same as for the default lock
registry (they have to be unlocked by the same thread that
locked them).

Updates from feedback

Add interface for JdbcClient so transactions can bind to proxy

Fix typo in exception message

Fix drop script

JdbcClient -> LockRepository

Make lock() contract more like native Lock

Make lockInterruptibly throw InterruptedException more

Delete all expired locks, not just the ones that we own

INT-4048: Polishing

* `DefaultLockRepository`: replace `prefix` only once in the `afterPropertiesSet()`
* Add JavaDocs to the `DefaultLockRepository`
* `JdbcLockRegistry`: add `Thread.sleep(100)` to lock loops do not request DB so often like in case of clean `while(true)`
* `JdbcLockRegistry`: implement more robust `tryLock(long time, TimeUnit unit)`. The logic mostly copied from `RedisLockRegistry`
* Add `testExclusiveAccess()` to be sure that JDBC locks have exclusive access to the data sequence

Document `JdbcLockRegistry`

Upgrade to SF-4.3 GA
This commit is contained in:
Dave Syer
2016-06-07 14:53:01 +01:00
committed by Artem Bilan
parent eca8536678
commit 7c2731dbb9
31 changed files with 1217 additions and 1 deletions

View File

@@ -974,3 +974,36 @@ a `stored-proc-outbound-gateway`
<int-jdbc:parameter name="ID" expression="payload" />
</int-jdbc:stored-proc-outbound-gateway>
----
[[jdbc-lock-registry]]
=== JDBC Lock Registry
Starting with _version 4.3_, the `JdbcLockRegistry` is available.
Certain components (for example aggregator and resequencer) use a lock obtained from a `LockRegistry` instance to ensure that only one thread is manipulating a group at a time.
The `DefaultLockRegistry` performs this function within a single component; you can now configure an external lock registry on these components.
When used with a shared `MessageGroupStore`, the `JdbcLockRegistry` can be use to provide this functionality across multiple application instances, such that only one instance can manipulate the group at a time.
When a lock is released by a local thread, another local thread will generally be able to acquire the lock immediately.
If a lock is released by a thread using a different registry instance, it can take up to 100ms to acquire the lock.
The `JdbcLockRegistry` is based on the `LockRepository` abstraction, where a `DefaultLockRepository` implementation is present.
The data base schema scripts are located in the `org.springframework.integration.jdbc` package divided to the particular RDBMS vendors.
For example the H2 DDL for lock table looks like:
[source,sql]
----
CREATE TABLE INT_LOCK (
LOCK_KEY CHAR(36),
REGION VARCHAR(100),
CLIENT_ID CHAR(36),
CREATED_DATE TIMESTAMP NOT NULL,
constraint LOCK_PK primary key (LOCK_KEY, REGION)
);
----
The `INT_` can be changed according to the target data base design requirements.
Therefore `prefix` property must be used on the `DefaultLockRepository` bean definition.
Sometimes it happens that one application has moved to the state when it can't release distributed lock - remove the particular record in the data base.
For this purpose such dead locks can be expired by the other application on the next locking invocation.
The `timeToLive` (TTL) option on the `DefaultLockRepository` is provided for this purpose.

View File

@@ -43,6 +43,11 @@ See <<stream-transformer>> for more information.
A new `IntegrationGraphServer` together with the `IntegrationGraphController` REST service are provided to expose the runtime model of a Spring Integration application as a graph.
See <<integration-graph>> for more information.
==== JDBC Lock Registry
A new `JdbcLockRegistry` is provided for distributed locks shared through the data base table.
See <<jdbc-lock-registry>> for more information.
[[x4.3-general]]
=== General Changes