【RedisCluster】redis-cluster pipeline测试
测试用例如下:
@Test
void redisPiplineTest(){
//测试redis-cluster pipline
List<Object> res=redisTemplate.executePipelined(new SessionCallback<Integer>() {
@Override
public <K, V> Integer execute(RedisOperations<K, V> operations) throws DataAccessException {
operations.opsForValue().get("lcc");
operations.opsForValue().get("clc");
operations.opsForValue().get("ccl");
return 0;
}
});
for (Object ob:res){
System.out.println(ob);
}
}
执行结果:

查看抛出异常的方法:
org.springframework.data.redis.connection.jedis.JedisClusterConnection#openPipeline
emm,可以看到JedisClusterConnection的openpipeline总是会抛出异常,而下面的方法可以看到与ConnectionFactory有关,而之前的帖子中我们提到可以根据slot分组之后pipeline,但是如果是
clusterConnection本身实现的原因,上面这个方案是不是真的行得通?

经测试pipeline只对一个key操作的时候也是上面异常
针对上面的疑问,仔细观察会发现JedisClusterConnection是spring-data-redis的实现,之前我们介绍分组slot的时候 实际上没有直接用spring,而是用的原生jedis。
再贴一次之前的实现(转载于https://www.jianshu.com/p/54a754c85f81)
@Test
void pipelineTestUsingJedis() {
Set<HostAndPort> jedisClusterNode = new HashSet<>();
HostAndPort hostAndPort1 = new HostAndPort("hostA", 7000);
HostAndPort hostAndPort2 = new HostAndPort("hostB", 7001);
HostAndPort hostAndPort3 = new HostAndPort("hostC", 7002);
jedisClusterNode.add(hostAndPort1);
jedisClusterNode.add(hostAndPort2);
jedisClusterNode.add(hostAndPort3);
JedisClusterPlus jedisClusterPlus = new JedisClusterPlus(jedisClusterNode, 2000, 2000, new JedisPoolConfig());
JedisSlotAdvancedConnectionHandler jedisSlotAdvancedConnectionHandler = jedisClusterPlus.getConnectionHandler();
String[] testKeys = {"foo", "bar", "xyz"};
Map<JedisPool, List<String>> poolKeys = new HashMap<>();
for (String key : testKeys) {
int slot = JedisClusterCRC16.getSlot(key);
JedisPool jedisPool = jedisSlotAdvancedConnectionHandler.getJedisPoolFromSlot(slot);
if (poolKeys.keySet().contains(jedisPool)) {
List<String> keys = poolKeys.get(jedisPool);
keys.add(key);
} else {
List<String> keys = new ArrayList<>();
keys.add(key);
poolKeys.put(jedisPool, keys);
}
}
for (JedisPool jedisPool : poolKeys.keySet()) {
Jedis jedis = jedisPool.getResource();
Pipeline pipeline = jedis.pipelined();
List<String> keys = poolKeys.get(jedisPool);
keys.forEach(key -> pipeline.get(key));
List result = pipeline.syncAndReturnAll();
System.out.println(result);
jedis.close();
}
}
}
class JedisClusterPlus extends JedisCluster {
public JedisClusterPlus(Set<HostAndPort> jedisClusterNode, int connectionTimeout, int soTimeout, final GenericObjectPoolConfig poolConfig) {
super(jedisClusterNode);
super.connectionHandler = new JedisSlotAdvancedConnectionHandler(jedisClusterNode, poolConfig,
connectionTimeout, soTimeout);
}
public JedisSlotAdvancedConnectionHandler getConnectionHandler() {
return (JedisSlotAdvancedConnectionHandler)this.connectionHandler;
}
}
public class JedisSlotAdvancedConnectionHandler extends JedisSlotBasedConnectionHandler {
public JedisSlotAdvancedConnectionHandler(Set<HostAndPort> nodes, GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) {
super(nodes, poolConfig, connectionTimeout, soTimeout);
}
public JedisPool getJedisPoolFromSlot(int slot) {
JedisPool connectionPool = cache.getSlotPool(slot);
if (connectionPool != null) {
// It can't guaranteed to get valid connection because of node
// assignment
return connectionPool;
} else {
renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
connectionPool = cache.getSlotPool(slot);
if (connectionPool != null) {
return connectionPool;
} else {
throw new JedisNoReachableClusterNodeException("No reachable node in cluster for slot " + slot);
}
}
}
可以看到最后在做pipeline的时候 还是用的jedis相关实现而不是jedisCluster,jedisCluster在其中只是起到了路由的作用.在jedisCluster的继承关系中确实没有发现Pipeline

浙公网安备 33010602011771号