java 处理redis 事物_SpringDataRedis事务处理

本文主要讲述如何在java里头使用redis进行cas操作。其实呢,redis不像memcached那样显示地支持cas操作,不过它有事务的概念。

准备

redis的乐观锁支持

Redis通过使用WATCH, MULTI, and EXEC组成的事务来实现乐观锁(注意没有用DISCARD),Redis事务没有回滚操作。在SpringDataRedis当中通过RedisTemplate的SessionCallback中来支持(否则事务不生效)。discard的话不需要自己代码处理,callback返回null,成的话,返回非null,依据这个来判断事务是否成功(没有抛异常)。

实例

@Test

public void cas() throws InterruptedException, ExecutionException {

String key = "test-cas-1";

ValueOperations strOps = redisTemplate.opsForValue();

strOps.set(key, "hello");

ExecutorService pool = Executors.newCachedThreadPool();

List> tasks = new ArrayList<>();

for(int i=0;i<5;i++){

final int idx = i;

tasks.add(new Callable() {

@Override

public Object call() throws Exception {

return redisTemplate.execute(new SessionCallback() {

@Override

public Object execute(RedisOperations operations) throws DataAccessException {

operations.watch(key);

String origin = (String) operations.opsForValue().get(key);

operations.multi();

operations.opsForValue().set(key, origin + idx);

Object rs = operations.exec();

System.out.println("set:"+origin+idx+" rs:"+rs);

return rs;

}

});

}

});

}

List> futures = pool.invokeAll(tasks);

for(Future f:futures){

System.out.println(f.get());

}

pool.shutdown();

pool.awaitTermination(1000, TimeUnit.MILLISECONDS);

}

输出

set:hello2 rs:null

set:hello3 rs:[]

set:hello1 rs:null

set:hello4 rs:null

set:hello0 rs:null

查看该值

127.0.0.1:6379> get test-cas-1

"\"hello3\""

SessionCallback

没有在SessionCallback里头执行watch、multi、exec,而是自己单独写

与数据库事务的混淆

template.setEnableTransactionSupport(true);

这个应该是支持数据库的事务成功才执行的意思。

/**

* Gets a Redis connection. Is aware of and will return any existing corresponding connections bound to the current

* thread, for example when using a transaction manager. Will create a new Connection otherwise, if

* {@code allowCreate} is true.

*

* @param factory connection factory for creating the connection

* @param allowCreate whether a new (unbound) connection should be created when no connection can be found for the

* current thread

* @param bind binds the connection to the thread, in case one was created

* @param enableTransactionSupport

* @return an active Redis connection

*/

public static RedisConnection doGetConnection(RedisConnectionFactory factory, boolean allowCreate, boolean bind,

boolean enableTransactionSupport) {

Assert.notNull(factory, "No RedisConnectionFactory specified");

RedisConnectionHolder connHolder = (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory);

if (connHolder != null) {

if (enableTransactionSupport) {

potentiallyRegisterTransactionSynchronisation(connHolder, factory);

}

return connHolder.getConnection();

}

if (!allowCreate) {

throw new IllegalArgumentException("No connection found and allowCreate = false");

}

if (log.isDebugEnabled()) {

log.debug("Opening RedisConnection");

}

RedisConnection conn = factory.getConnection();

if (bind) {

RedisConnection connectionToBind = conn;

if (enableTransactionSupport && isActualNonReadonlyTransactionActive()) {

connectionToBind = createConnectionProxy(conn, factory);

}

connHolder = new RedisConnectionHolder(connectionToBind);

TransactionSynchronizationManager.bindResource(factory, connHolder);

if (enableTransactionSupport) {

potentiallyRegisterTransactionSynchronisation(connHolder, factory);

}

return connHolder.getConnection();

}

return conn;

}

不要跟本文的乐观锁说的事务混淆在一起。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中实现Redis的实时推送可以使用Redis的发布/订阅功能。Redis的发布/订阅功能是一种消息传递模式,它允许发送者(发布者)向一个或多个接收者(订阅者)发送消息。下面是使用Spring Boot和Redis实现Redis消息发布与监听的示例代码: 1. 添加Redis依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接 在application.properties文件中添加Redis连接配置: ``` spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 定义消息监听器 定义一个Redis消息监听器,用于接收订阅的消息。示例代码如下: ``` @Component public class RedisMessageListener implements MessageListener { @Override public void onMessage(Message message, byte[] pattern) { System.out.println("Received message: " + message.toString()); } } ``` 4. 发布消息 在需要发布消息的地方,注入RedisTemplate对象,调用convertAndSend方法即可发送消息。示例代码如下: ``` @Autowired private RedisTemplate<String, Object> redisTemplate; public void sendMessage(String channel, String message) { redisTemplate.convertAndSend(channel, message); } ``` 5. 订阅消息 在启动类中定义Redis消息监听器容器,并将Redis消息监听器注册到容器中。示例代码如下: ``` @SpringBootApplication public class Application implements CommandLineRunner { @Autowired private RedisMessageListener redisMessageListener; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(redisConnectionFactory()); container.addMessageListener(redisMessageListener, new PatternTopic("test")); container.start(); } @Bean public JedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName("127.0.0.1"); config.setPort(6379); return new JedisConnectionFactory(config); } } ``` 以上代码中,容器使用Redis连接工厂创建,监听器注册到容器中,并使用PatternTopic定义订阅的消息通道。 这样,当有消息发布到指定通道时,RedisMessageListener的onMessage方法会被触发,从而实现了Redis的实时推送功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值