java.lang.UnsupportedoperationException:Pipeline iscurrentlvsupported for JedisClusterConnection

最近项目上了Redis集群,有相关的业务地方使用到了pipelineget(),之前是单节点,上了集群之后,发现java.lang.UnsupportedoperationException:Pipeline iscurrentlvsupported for JedisClusterConnection,下方异常是我在内部ELK系统上查询到的
在这里插入图片描述

解决方案:
思想架构:
在这里插入图片描述
1.获取每个节点上可以分配到的key

    private Map<RedisClusterNode, List<String>> getNodeKeyMap(Collection<String> keys, RedisClusterConnection redisClusterConnection) {
        //定义的map以redis的节点为key  list为value,此处的list存放的该节点下需要存储的key值
        HashMap<RedisClusterNode, List<String>> nodeKeyMap = new HashMap<>(8);

        //通过计算每个key的槽点,获取所有的节点
        Iterable<RedisClusterNode> redisClusterNodes = redisClusterConnection.clusterGetNodes();
        for (RedisClusterNode redisClusterNode : redisClusterNodes) {
            //得到节点的槽位的范围
            RedisClusterNode.SlotRange slotRange = redisClusterNode.getSlotRange();
            for (String key : keys) {
                //利用redis的key的hash算法得到该key对应的槽位
                int slot = JedisClusterCRC16.getSlot(key);
                if (slotRange.contains(slot)) {
                    List<String> list = nodeKeyMap.get(redisClusterNode);
                    if (null == list) {
                        list = new ArrayList<>();
                        nodeKeyMap.putIfAbsent(redisClusterNode, list);
                    }
                    //将对应的key放入进去
                    list.add(key);
                }
            }
        }
        
        return nodeKeyMap;
    }

2.获取连接,打开pipeline,执行get/set操作

    public void clusterPipelineSet(Map<String, Object> data) {
        Set<String> keys = data.keySet();
        //获取key的序列化策略
        RedisSerializer keySerializer = redisTemplate.getKeySerializer();
        RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
        //获取集群的连接对象
        RedisClusterConnection redisClusterConnection = redisTemplate.getConnectionFactory().getClusterConnection();
        try {

            Map<RedisClusterNode, List<String>> nodeKeyMap = getNodeKeyMap(keys, redisClusterConnection);
            //开始遍历通过管道往redis中放入数据 遍历上边定义的map
            for (Map.Entry<RedisClusterNode, List<String>> clusterNodeListEntry : nodeKeyMap.entrySet()) {
                //连接节点
                RedisClusterNode redisClusterNode = clusterNodeListEntry.getKey();
                //获取到每个节点的JedisPool对象  关于jedis和redistemplate的关系下边会进行简单介绍。
                JedisPool jedisPool = ((JedisCluster) redisClusterConnection.getNativeConnection()).getClusterNodes()
                        .get(new HostAndPort(redisClusterNode.getHost(), redisClusterNode.getPort()).toString());
                List<String> nodeListEntryValue = clusterNodeListEntry.getValue();
                //从池子中拿出对应的jedis对象
                Jedis jedis = jedisPool.getResource();
                try {
                    //开始使用单节点的pipline对象进行操作。
                    Pipeline pipeline = jedis.pipelined();
                    //************************接下来的操作就是对应利用pipline获取值和set值可以根据业务需求选取******************************

                    //往redis中放入值
                    for (String nodeKey : nodeListEntryValue) {
                        pipeline.set(keySerializer.serialize(nodeKey), valueSerializer.serialize(data.get(nodeKey)));
                    }
                    pipeline.sync();

                    //*************************************************************************************************************

                    pipeline.close();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    jedis.close();
                }

            }
        } finally {
            RedisConnectionUtils.releaseConnection(redisClusterConnection, redisTemplate.getConnectionFactory());
        }
    }
   public List<Object> clusterPiplineGet(List<String> keys) throws Exception {

        //获取key的序列化策略
        RedisSerializer keySerializer = redisTemplate.getKeySerializer();
        List<Object> result = new ArrayList<>(8);
        //获取集群的连接对象
        RedisClusterConnection redisClusterConnection = redisTemplate.getConnectionFactory().getClusterConnection();
        try {
            Map<RedisClusterNode, List<String>> nodeKeyMap = getNodeKeyMap(keys, redisClusterConnection);
            //开始遍历通过管道往redis中放入数据 遍历上边定义的map
            for (Map.Entry<RedisClusterNode, List<String>> clusterNodeListEntry : nodeKeyMap.entrySet()) {
                //连接节点
                RedisClusterNode redisClusterNode = clusterNodeListEntry.getKey();
                //获取到每个节点的JedisPool对象  关于jedis和redistemplate的关系下边会进行简单介绍。
                JedisPool jedisPool = ((JedisCluster) redisClusterConnection.getNativeConnection()).getClusterNodes()
                        .get(new HostAndPort(redisClusterNode.getHost(), redisClusterNode.getPort()).toString());
                List<String> nodeListEntryValue = clusterNodeListEntry.getValue();
                //从池子中拿出对应的jedis对象
                Jedis jedis = jedisPool.getResource();
                List<Response<byte[]>> responses = new ArrayList<>();
                try {
                    //开始使用单节点的pipline对象进行操作。
                    Pipeline pipeline = jedis.pipelined();
                    //************************接下来的操作就是对应利用pipline获取值和set值可以根据业务需求选取******************************

                    //从redis中获取值
                    for (String nodeKey : nodeListEntryValue) {
                        responses.add(pipeline.get(keySerializer.serialize(nodeKey)));
                    }
                    List<Object> objects = pipeline.syncAndReturnAll();
                    if (!CollectionUtils.isEmpty(objects)) {
                        result.addAll(objects);
                    }

                    pipeline.close();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    jedis.close();
                }

            }
        } finally {
            RedisConnectionUtils.releaseConnection(redisClusterConnection, redisTemplate.getConnectionFactory());
        }
        return result.stream().filter(r -> Objects.nonNull(r)).collect(Collectors.toList());
    }

3.Test测试类

    @Test
    public void testClusterPipeline() throws Exception {

        List<String> keys = Lists.newArrayList("aa1", "bb1","cc1");
        List<Object> objects = taRedisService.clusterPiplineGet(keys);
        System.out.println("objects = " + objects);
        for (Object object : objects) {
            byte[] b = (byte[]) object;
            String s = new String(b, CharsetUtil.UTF_8);
            System.out.println("s = " + s);
        }
    }
    
    @Test
    public void testClusterPipelineSet() {
        Map<String, Object> data = new HashMap<>();
        data.put("aa1", "v1");
        data.put("bb1", "v2");
        data.put("cc1", "v3");
        taRedisService.clusterPipelineSet(data);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coffee_babe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值