Redisのピット:spring-data-redisのRedisトランザクション
21243 ワード
Redisのピット:spring-data-redisのRedisトランザクションRedisのピット:RedisトランザクションRedisのピットを理解する:RedisとMySQLのトランザクションの区別Transactionのピット:データベーストランザクションTransactionのピット:SpringのTransactionの構成と非構成の区別Transactionのピット:sql実行結果を分析し、トランザクションrollbackをアクティブに促す
SessionCallback
さらに、
使用方法は次のとおりです.
戻る前に、RedisTemplateはそのvalue、hash key、hash valueシーケンサを使用してexecのすべての結果を逆シーケンス化します.トランザクション結果にカスタムシーケンス化器を渡す追加のexecメソッド.
@Transactionalサポート
以上、セッションCallbackは、)を追加し、トランザクション・接点を登録します.TransactionSynchronizationManagerを呼び出すことに相当します.setActualTransactionActive ( true ); setEnableTransactionSupport(true)により を明示的に有効にする.
redisTemplateインスタンスは、デフォルトでexecute(RedisCallback action)を呼び出します.メソッドの内容は次のとおりです.
enableTransactionSupport=trueは、現在の
接続バインディングに成功し、現在の すべての コマンド そうでなければ
トランザクションサポートを有効にすると、次のようになります.
上記のサンプルコードはSpring公式サイトから与えられ、3番目は明らかに org.springframework.data.redis.core.RedisConnectionUtils.potentiallyRegisterTransactionSynchronisation
宣言
2つのサポートトランザクション: はトランザクションをサポートせず、
SessionCallback
Redis
は、multi
、exec
、またはdiscard
コマンドによってトランザクションサポートを提供し、これらのアクションはRedisTemplate
でも同様に利用可能である.ただし、RedisTemplate
ではRedisCallBackインタフェースがデフォルトで使用されており、同じ接続を使用して同じトランザクション内のすべての操作を実行することは保証されていません(この場合、Transaction
は無効です).さらに、
Spring Data Redis
は、
が複数の動作を実行することを保証する必要がある場合、例えば「Redis
を使用する必要がある場合」に使用するためのSessionCallbackインターフェースを提供する.次のように見えます.public T execute(SessionCallback session) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);// 8
try {
return session.execute(this);
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
RedisTemplate.execute(SessionCallback session)
方法の 8
はすでに
をした.使用方法は次のとおりです.
//execute a
transaction
List<
Object
> txResults = redisTemplate.
execute
(new
SessionCallback
<List<
Object
>>() {
public
List<
Object
>
execute
(RedisOperations operations)
throws
DataAccessException {
operations.
multi
();
operations.
opsForSet
().add("key", "value1");
//
This
will
contain
the
results
of
all
ops
in
the
transaction
return
operations.
exec
();
}
});
System.out.
println
("
Number
of
items
added
to
set
: " + txResults.get(0));
戻る前に、RedisTemplateはそのvalue、hash key、hash valueシーケンサを使用してexecのすべての結果を逆シーケンス化します.トランザクション結果にカスタムシーケンス化器を渡す追加のexecメソッド.
@Transactionalサポート
以上、セッションCallback
によって、multi
、exec
、またはdiscard
を実現することによって、Redis
をサポートすることができるが、これは複雑であり、Redis (opsXXX.X)
が実行する位置にも限界がある(機能に影響を及ぼさないが).しかし、Spring
では、2ステップでより簡単にできます.method
に注記**@TransactionalまたはXml構成*(RedisTemplate
インスタンスの
(デフォルトでは無効)/** Sample Configuration **/
@Configuration
public class RedisTxContextConfiguration {
@Bean
public StringRedisTemplate redisTemplate() {
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
// explicitly enable transaction support
template.setEnableTransactionSupport(true);
return template;
}
}
redisTemplateインスタンスは、デフォルトでexecute(RedisCallback action)を呼び出します.メソッドの内容は次のとおりです.
public
<T> T
execute
(RedisCallback<T> action,
boolean
exposeConnection,
boolean
pipeline){
/**
* ……
*/
try {
if (enableTransactionSupport) {
//
only
bind
resources
in
case
of
potential
transaction
synchronization
conn = RedisConnectionUtils.
bindConnection
(factory, enableTransactionSupport);
}
else
{
conn = RedisConnectionUtils.
getConnection
(factory);
}
/**
* ……
*/
}
public
static
RedisConnection
bindConnection
(RedisConnectionFactory factory,
boolean
enableTransactionSupport) {
/**
* ……
*/
RedisConnection conn = factory.
getConnection
();
RedisConnection connectionToBind = conn;
//redisTemplate , transactionManager
if (enableTransactionSupport &&
isActualNonReadonlyTransactionActive
()) {
connectionToBind =
createConnectionProxy
(conn, factory);
}
/**
* ……
*/
return
conn;
}
enableTransactionSupport=trueは、現在の
Thread
にRedisConnection
をバインドしようとします.接続は、isActualNonReadonlyTransactionActive=trueである場合にのみ正常にバインドされます.接続バインディングに成功し、
MULTI
がトリガーされます.MULTI
が呼び出されると、RedisConnection
はwrite
に並びます.readonly
、例えばKEYS
は、新しい(非Thread
バインド)RedisConnection
に配布される.EXEC
またはDISCARD
SpringAOPの動的プロキシオブジェクトに渡す呼び出し:
プロセス中に
(デフォルトのRuntimeException
およびそのサブクラス)がない場合、EXEC
が呼び出され、コマンドキューが実行される.DISCARD
、コマンドキューをクリアします.トランザクションサポートを有効にすると、次のようになります.
/** Usage Constrainsts **/
//
executed
on
thread
bound
connection
template.
opsForValue
().set("foo", "bar");
//
read
operation
executed
on a
free
(
not
tx-
aware
)
connection template.
keys
("*");
//
returns
null
as
values
set
within
transaction
are
not
visible
template.
opsForValue
().get("foo");
上記のサンプルコードはSpring公式サイトから与えられ、3番目は明らかに
WATCH
コマンドが
を開いた後の結果である.しかし、少なくとも本人が使用しているspring-data-redis-1.8.10では.RELEASE . JArでは、<
dependency
>
<
groupId
>org.springframework.data
groupId
>
<
artifactId
>spring-data-redis
artifactId
>
<
version
>1.8.10.RELEASE
version
>
dependency
>
WATCH
コマンドは使用されていません.親測定
の効果は存在しません(自分の依存バージョンに基づいて試してみてください).ここにコードが表示されます.
private
static
void
potentiallyRegisterTransactionSynchronisation
(RedisConnectionHolder connHolder,
final
RedisConnectionFactory factory) {
if (
isActualNonReadonlyTransactionActive
()) {
if (!connHolder.
isTransactionSyncronisationActive
()) {
connHolder.
setTransactionSyncronisationActive
(
true
);
RedisConnection conn = connHolder.
getConnection
();
conn.
multi
();// conn.watch()
TransactionSynchronizationManager.
registerSynchronization
(new
RedisTransactionSynchronizer
(connHolder, conn,
factory));
}
}
}
宣言
RedisTemplateインスタンス2つの
RedisTemplate
例?commands
または
、または
、データ整合性の維持.command
は直ちに実行され、
に即時に戻り、さらに
に戻る./**
Sample
Configuration
**/
@Configuration
public
class
RedisTxContextConfiguration
{
@Bean
public
StringRedisTemplate
redisTransactionTemplate
() {
StringRedisTemplate template = new
StringRedisTemplate
(
redisConnectionFactory
());
//
explicitly
enable
transaction
support
template.
setEnableTransactionSupport
(
true
);
return
template;
}
@Bean
public
StringRedisTemplate
redisTemplate
() {
StringRedisTemplate template = new
StringRedisTemplate
(
redisConnectionFactory
());
return
template;
}
}