1
回答
使用Spring-data-redis遇到的问题
科大讯飞通用文字识别100000次/天免费使用。立即申请   

使用Redis+Sentinel搭建集群,3个Sentinel监控20个Redis主从实例,客户端实现数据分片,使用ShardedJedis编写客户端。自己实现了ShardedJedisConnectionFactory.java,ShardedJedisSentinelPool.java。

使用Sping-data-redis框架,结果压力测试的时候发现TPS也就一万多,连接无法保持(200个并发时连接跳动得很厉害),如果不用Spring-data-redis框架直接调用ShardedJedisConnectionFactory中的ShardedJedisSentinelPool拿连接就没有问题,每个实例都能保持200个长连接。

JProfiler结果如下,CPU时间都花在建立连接上了。


网上搜了下解决办法,有人说spring-data-redis中的redistemplate中每次指令执行都会新建一个连接http://jimgreat.iteye.com/blog/1596058/调试的时候发现的确如此,redistemplate.java的execute方法在enableTransactionSupport为false的情况下,每次都会用工厂类新建一个连接conn = RedisConnectionUtils.getConnection(factory);导致不停地创建新的连接。源码如下:

public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
		Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
		Assert.notNull(action, "Callback object must not be null");

		RedisConnectionFactory factory = getConnectionFactory();
		RedisConnection conn = null;
		try {

			if (enableTransactionSupport) {
				// only bind resources in case of potential transaction synchronization
				conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
			} else {
				conn = RedisConnectionUtils.getConnection(factory);
			}

			boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);

			RedisConnection connToUse = preProcessConnection(conn, existingConnection);

			boolean pipelineStatus = connToUse.isPipelined();
			if (pipeline && !pipelineStatus) {
				connToUse.openPipeline();
			}

			RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
			T result = action.doInRedis(connToExpose);

			// close pipeline
			if (pipeline && !pipelineStatus) {
				connToUse.closePipeline();
			}

			// TODO: any other connection processing?
			return postProcessResult(result, connToUse, existingConnection);
		} finally {

			if (!enableTransactionSupport) {
				RedisConnectionUtils.releaseConnection(conn, factory);
			}
		}
	}
目前貌似只能想办法改RedisTemplate.java的源码了,在执行操作的时候想办法拿到连接池,直接从池中拿连接。

Redis新人,求助大拿,看看有没有更好的办法。


举报
tamama1030
发帖于3年前 1回/2K+阅
顶部