`
zhanghaj00
  • 浏览: 64096 次
社区版块
存档分类
最新评论

Spring-data-redis 第二天(事务)

阅读更多

从今天开始,开始慢慢学习Spring 对 redis 中各种特性的支持,事务啦,pipeline啦,sharding啦,cache啦,还有就是分布式中和用jedispool 等等之中的东西,东西好多呀。头大了。。

 

1.首先看Jedis 原生态的对事务的处理

 

Jedis jedis = new Jedis("192.168.137.100",6379);
Transaction tx = jedis.multi();
		
for(int i=0;i<1000; i++){
	tx.set("zhang"+i, "hao"+i);
}
List<Object> result = tx.exec();
		
jedis.disconnect();

 其中可以用Jedis 的 watch(key) 来实现乐观锁,有一点,如果事务处理器中出现错误,不会回滚,出错那条不会处理,还有Jedis的 discard 方法来取消事务,可以自己模拟多线程来看看这两个方法的使用,还有一点,事务是异步执行,所以不能再事务中调用get 同步查询结果,都是坑呀。。。。

 

2.Spring中对Redis 事务的支持

 (1)

                rt.watch("zhang");
		rt.multi();
		for(int i=0;i<10;i++){
			BoundHashOperations<String, String, String> hs = rt.boundHashOps("zhang");
			hs.put("zhang"+i, "hao"+i);
		}
		rt.exec();

   我们按照上面的思路,然后写下了上面这段代码。然后就报错了: java.lang.NullPointerException,

好吧 看下面一段代码:

SessionCallback<String> sessionCallback = new SessionCallback<String>() {
			
			@Override
			public <K, V> String execute(RedisOperations<K, V> operation)
					throws DataAccessException {
				
				operation.multi();
				for(int i=0;i<10;i++){
					BoundHashOperations<String, String, String> hs = ((RedisTemplate)operation).boundHashOps("zhang");
					hs.put("zhang"+i, "hao"+i);
				}
				operation.exec();
				return null;
			}
		};
		rt.execute(sessionCallback);

 这段代码就执行成功了,为什么呢。只有Google 大神们是怎么解释了:

首先还是看源码:

public void multi() {
		execute(new RedisCallback<Object>() {

			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				connection.multi();
				return null;
			}
		}, true);
	}

 这里要实现一个指定返回类型的RedisCallback接口,这个接口只有一个函数doInRedis

doInRedis的参数是RedisConnection接口,spring-data-redis针对不的Redis Java Client都有对应的 RedisConnection实现:

JedisConnection

JredisConnection

RjcConnection

SrpConnection

目的就是将不同Client的API统一了一下,可以看成是Adapter吧 。

 

execute这个是模板函数,主是处理连接的问题。

spring-data-redis 针对不的 Redis Java Client 也都实现了相应的 RedisConnectionFactory,来获取连接。  

 

比如 JedisConnectionFactory 内部是通过 JedisPool 来实现连接工厂。

    public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {  
        Assert.notNull(action, "Callback object must not be null");  
      
        RedisConnectionFactory factory = getConnectionFactory();  
        RedisConnection conn = RedisConnectionUtils.getConnection(factory);  
      
        boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);  
        preProcessConnection(conn, existingConnection);  
      
        boolean pipelineStatus = conn.isPipelined();  
        if (pipeline && !pipelineStatus) {  
            conn.openPipeline();  
        }  
      
        try {  
            RedisConnection connToExpose = (exposeConnection ? conn : createRedisConnectionProxy(conn));  
            T result = action.doInRedis(connToExpose);  
      
            // close pipeline  
            if (pipeline && !pipelineStatus) {  
                conn.closePipeline();  
            }  
      
            // TODO: any other connection processing?  
            return postProcessResult(result, conn, existingConnection);  
        } finally {  
            RedisConnectionUtils.releaseConnection(conn, factory);  
        }  
    }  

 可以看到,正常情况下每次connection都是新的,那上上一段代码中得multi 就没用了。

这样。好吧 我懒得复制了,可以看下这个大神的博客:http://jimgreat.iteye.com/blog/1596058 讲的很清楚sessioncallback如何捆绑session。

 

 

http://stackoverflow.com/questions/10750626/transactions-and-watch-statement-in-redis  这段解释了watch的操作,非常明白 一看就懂,

 

今天太忙了,只稍微看了看事务这一快,感觉支持的不是很好,明天继续看吧 ,加油。

 

分享到:
评论
1 楼 果粒儿我是 2018-01-25  
虎头蛇尾...后面实在没懂。。。

相关推荐

Global site tag (gtag.js) - Google Analytics