首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >redis实战第十五篇 redis cluster的批处理中ask重定向解决方案

redis实战第十五篇 redis cluster的批处理中ask重定向解决方案

作者头像
我是李超人
发布2020-08-20 15:26:20
发布2020-08-20 15:26:20
1K0
举报

ask重定向现象请参考【传送门

分别使用mget和pipline做批处理

1.使用mget批量获取,如果存在重定向问题,会抛出异常。

代码语言:javascript
复制
    @Test
    public void testMget(){
        JedisCluster jedis = RedisClusterUtil.getJedis();
        List<String> results = null;
        results = jedis.mget("user:{info}:id","user:{info}:age");
        for(String res:results){
            System.out.println(res);
        }
        results = jedis.mget("user:{info}:id","user:{info}:age","user:{info}:name","user:{info}:email");
        for(String res:results){
            System.out.println(res);
        }
    }

返回结果如下所示,第一次mget执行成功,是因为两个键都迁移完成,第二次获取失败是因为存在ask重定向问题。

代码语言:javascript
复制
232132
20

redis.clients.jedis.exceptions.JedisDataException: TRYAGAIN Multiple keys request during rehashing of slot

2.使用pipline做批量处理

代码语言:javascript
复制
@Test
    public void testPiplione(){
        //创建JedisCluster时,节点地址可以只填写部分,集群内部可以通过cluster nodes获取所有节点信息
        JedisSlotBasedConnectionHandler connectionHandler = new JedisCluster(new HostAndPort("192.168.0.31",6380),1000,1000,5,"1234@abcd",new JedisPoolConfig()){
            public JedisSlotBasedConnectionHandler getConnectionHandler() {
                return (JedisSlotBasedConnectionHandler) super.connectionHandler;
            }
        }.getConnectionHandler();
        List<String> keys = Arrays.asList("user:{info}:id","user:{info}:age","user:{info}:name","user:{info}:email");
        Jedis jedis = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(keys.get(3)));
        try {
            Pipeline pipelined = jedis.pipelined();
            for (String key : keys) {
                pipelined.get(key);
            }
            List<Object> results = pipelined.syncAndReturnAll();
            for (Object result : results) {
                System.out.println(result);
            }
        } finally {
            jedis.close();
        }
    }

批处理结果如下,当存在重定向问题时,pipline不会抛出异常,而是直接返回异常对象,并且成功迁移的键能获取到值。

代码语言:javascript
复制
redis.clients.jedis.exceptions.JedisAskDataException: ASK 5642 192.168.0.33:6380
redis.clients.jedis.exceptions.JedisAskDataException: ASK 5642 192.168.0.33:6380
peter
132132@163.com

基于异常结果对象,可以获取到对应的重定向节点信息,根据获取到的节点信息获取连接再次发送请求。

代码语言:javascript
复制
@Test
    public void testPiplione2(){
        JedisSlotBasedConnectionHandler connectionHandler = new JedisCluster(new HostAndPort("192.168.0.31",6380),1000,1000,5,"1234@abcd",new JedisPoolConfig()){
            public JedisSlotBasedConnectionHandler getConnectionHandler() {
                return (JedisSlotBasedConnectionHandler) super.connectionHandler;
            }
        }.getConnectionHandler();
        List<String> keys = Arrays.asList("user:{info}:id","user:{info}:age","user:{info}:name","user:{info}:email");
        Jedis jedis = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(keys.get(3)));
        try {
            Pipeline pipelined = jedis.pipelined();
            for (String key : keys) {
                pipelined.get(key);
            }
            List<Object> results = pipelined.syncAndReturnAll();
            for (int i =0 ; i<keys.size() ; i++) {
                // 键顺序和结果顺序,Pipeline严格按照键发送的顺序返回结果,即使出现异常也是如此
                Object result = results.get(i);
                //判断是否是异常结果对象
                if (result != null && result instanceof JedisAskDataException) {
                    JedisAskDataException askException = (JedisAskDataException) result;
                    //根据异常结果对象获取节点信息
                    HostAndPort targetNode = askException.getTargetNode();
                    //根据节点信息获取jedis连接
                    Jedis targetJedis = connectionHandler.getConnectionFromNode(targetNode);
                    try {
                        // 执行asking
                        targetJedis.asking();
                        // 获取key并执行
                        String key = keys.get(i);
                        String targetResult = targetJedis.get(key);
                        System.out.println(targetResult);
                    } finally {
                        targetJedis.close();
                    }
                } else {
                    System.out.println(result);
                }
            }
        }finally {
            jedis.close();
        }
    }

以下是执行结果,可以看出pipline可以根据返回的异常结果对象,获取ask重定向节点信息,发送ask请求,获取返回结果,这点和mget不一样,mget出现ask重定向问题时会直接抛出异常。

代码语言:javascript
复制
232132
20
peter
132132@163.com

集群环境下的批量操作场景,建议优先选择pipline,这样不仅可以处理slot迁移过程的ask重定向问题,还可以提高redis的IO效率。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/02/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档