Redis集群批量操作

Redis在3.0版正式引入了集群这个特性,扩展变得非常简单。然而当你开心的升级到3.0后,却发现有些很好用的功能现在工作不了了, 比如我们今天要聊的pipeline功能等批量操作。

Redis集群是没法执行批量操作命令的,如mget,pipeline等。这是因为redis将集群划分为16383个哈希槽,不同的key会划分到不同的槽中。但是,Jedis客户端提供了计算key的slot方法,已经slot和节点之间的映射关系,通过这两个数据,就可以计算出每个key所在的节点,然后使用pipeline获取数据。

/**
 * 根据key计算slot,
 * 再根据slot计算node,
 * 获取pipeline
 * 进行批量操作
 */
public class BatchUtil {
    public static Map<String, String> mget(JedisCluster jc, String... keys){
        Map<String, String> resMap = new HashMap<>();
        if(keys == null || keys.length == 0){
            return resMap;
        }
        //如果只有一条,直接使用get即可
        if(keys.length == 1){
            resMap.put(keys[0], jc.get(keys[0]));
            return resMap;
        }

        //JedisCluster继承了BinaryJedisCluster
        //BinaryJedisCluster的JedisClusterConnectionHandler属性
        //里面有JedisClusterInfoCache,根据这一条继承链,可以获取到JedisClusterInfoCache
        //从而获取slot和JedisPool直接的映射
        MetaObject metaObject = SystemMetaObject.forObject(jc);
        JedisClusterInfoCache cache = (JedisClusterInfoCache) metaObject.getValue("connectionHandler.cache");
        //保存地址+端口和命令的映射
        Map<JedisPool, List<String>> jedisPoolMap = new HashMap<>();
        List<String> keyList = null;
        JedisPool currentJedisPool = null;
        Pipeline currentPipeline = null;

        for(String key : keys){
            //计算哈希槽
            int crc = JedisClusterCRC16.getSlot(key);
            //通过哈希槽获取节点的连接
            currentJedisPool = cache.getSlotPool(crc);
            //由于JedisPool作为value保存在JedisClusterInfoCache中的一个map对象中,每个节点的
            //JedisPool在map的初始化阶段就是确定的和唯一的,所以获取到的每个节点的JedisPool都是一样
            //的,可以作为map的key
            if(jedisPoolMap.containsKey(currentJedisPool)){
                jedisPoolMap.get(currentJedisPool).add(key);
            }else{
                keyList = new ArrayList<>();
                keyList.add(key);
                jedisPoolMap.put(currentJedisPool, keyList);
            }
        }

        //保存结果
        List<Object> res = new ArrayList<>();
        //执行
        for(Entry<JedisPool, List<String>> entry : jedisPoolMap.entrySet()){
            try {
                currentJedisPool = entry.getKey();
                keyList = entry.getValue();
                //获取pipeline
                currentPipeline = currentJedisPool.getResource().pipelined();
                for(String key : keyList){
                    currentPipeline.get(key);
                }
                //从pipeline中获取结果
                res = currentPipeline.syncAndReturnAll();
                currentPipeline.close();
                for(int i=0; i<keyList.size(); i++){
                    resMap.put(keyList.get(i), res.get(i)==null ? null : res.get(i).toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
                return new HashMap<>();
            }
        }
        return resMap;
    }
}

原文地址:https://www.cnblogs.com/xiangpeng/p/10327934.html

时间: 2024-10-29 09:42:57

Redis集群批量操作的相关文章

redis 集群配置实战

最近研究Redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 release出来后,换掉memCache 集群. 一:关于redis cluster 1:redis cluster的现状 reids-cluster计划在redis3.0中推出,可以看作者antirez的声明:http://antirez.com/news/49 (ps:跳票了好久,今年貌似加快速度了),目前的最新版本是redis3 beta2(2.9.51). 作者的目标:Redis Cl

[转载] Redis集群搭建最佳实践

转载自http://blog.csdn.net/sweetvvck/article/details/38315149?utm_source=tuicool 要搭建Redis集群,首先得考虑下面的几个问题; Redis集群搭建的目的是什么?或者说为什么要搭建Redis集群? Redis集群搭建的目的其实也就是集群搭建的目的,所有的集群主要都是为了解决一个问题,横向扩展. 在集群的概念出现之前,我们使用的硬件资源都是纵向扩展的,但是纵向扩展很快就会达到一个极限,单台机器的Cpu的处理速度,内存大小,

Redis集群搭建最佳实践

要搭建Redis集群,首先得考虑下面的几个问题; Redis集群搭建的目的是什么?或者说为什么要搭建Redis集群? Redis集群搭建的目的其实也就是集群搭建的目的,所有的集群主要都是为了解决一个问题,横向扩展. 在集群的概念出现之前,我们使用的硬件资源都是纵向扩展的,但是纵向扩展很快就会达到一个极限,单台机器的Cpu的处理速度,内存大 小,硬盘大小没办法一直满足需求,而且机器纵向扩展的成本是相当高的.集群的出现就是能够让多台机器像一台机器一样工作,实现了资源的横向扩展. Redis是内存型数

redis集群讨论

一.生产应用场景 二.存储架构演变 三.应用最佳实践 四.运维经验总结 第1.2节:介绍redis cluster在唯品会的生产应用场景,以及存储架构的演变.第3节:redis cluster的稳定性,应用成熟度,踩到过那些坑,如何解决这些问题?这部分是大家比较关心的内容.第4节:简单介绍大规模运营的一些经验,包括部署.监控.管理以及redis工具开发. 一.生产应用场景 1.业务范围 redis cluster在唯品会主要应用于后端业务,用作内存存储服务.主要大数据实时推荐/ETL.风控.营销

redis使用基础(六) ——Redis集群

redis使用基础(六) --Redis集群 (转载请附上本文链接--linhxx) 一.单台服务器 单台redis服务器,会出现单点故障,且需要承受所有的负载.另外,所有的内容都存在单个服务器上,该服务器会成为瓶颈. 使用多台服务器作为redis服务器,需要考虑集群管理,如数据一致性.增加节点.故障恢复等问题.redis对处理这些问题有一套方案. 二.复制 redis的持久化功能保证了数据的持久性,但是如果服务器故障,数据还是可能会丢失,因此需要将数据备份到其他服务器.当一台服务器内容更新,会

深入剖析Redis系列: Redis集群模式搭建与原理详解

前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 在 分布式 方面的需求.当遇到 单机内存.并发.流量 等瓶颈时,可以采用 Cluster 架构方案达到 负载均衡 的目的. 本文将从 集群方案.数据分布.搭建集群.节点通信.集群伸缩.请求路由.故障转移.集群运维 等几个方面介绍 Redis Cluster. 正文 1. Redis集群方

Redis 集群(三)

为什么为有集群 在 Redis3 版本之前,每台 Redis 机器需要存储所有 Redis key ,这要求每台 Redis 机器有足够大的内存 而且只能是主节点写,从节点读,对于高并发情况下会有性能瓶颈 虽然有哨兵模式来保证服务的高用,但是切换主节点还是需要时间的(实测) 分布式数据库 分布式数据库指将数据均匀的分布到每个节点上,可以做数据冗余来排除故障,每个节点负责数据的一个子集 如何进行分区 常见的分区规则 哈希分区,顺序分区,Redis 集群使用了哈希分区 虚拟槽分区 方式 所有的键根据

redis 集群

redis 集群 redis集群是redis提供分布式数据库方案, 集群通过分片(Sharding)来进行数据共享,并提供复制和故障转移功能. 节点 redis集群通常由多个节点(node)组成,在开始每个node 都是相互独立的. 要组建成真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群. 命令 cluster meet <ip> <port> 向一个node 发送命令 cluster meet,让节点与ip/port所指定的节点 进行握手(hand

Redis集群的高可用测试(含Jedis客户端的使用)

Redis集群的使用测试(Jedis客户端的使用) 1.  Jedis客户端建议升级到最新版(当前为2.7.3),这样对3.0.x集群有比较好的支持. https://github.com/xetorthio/jedis http://mvnrepository.com/artifact/redis.clients/jedis 2.  直接在Java代码中链接Redis集群: // 数据库链接池配置 JedisPoolConfig config = new JedisPoolConfig();