【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

posted @ 2020-12-01 11:11  l2c  阅读(359)  评论(0)    收藏  举报