在Redis集群中使用pipeline批量插入

由于项目中需要使用批量插入功能, 所以在网上查找到了Redis 批量插入可以使用pipeline来高效的插入, 示例代码如下:

String key = "key";
Jedis jedis = new Jedis("xx.xx.xx.xx");
Pipeline p = jedis.pipelined();
List<String> myData = .... //要插入的数据列表
for(String data: myData){
    p.hset(key, data);
}
p.sync();
jedis.close();

但实际上遇到的问题是,项目上所用到的Redis是集群,初始化的时候使用的类是JedisCluster而不是Jedis. 去查了JedisCluster的文档, 并没有发现提供有像Jedis一样的获取Pipeline对象的 pipelined()方法.

Google了一下, 发现了解决方案.

Redis集群规范有说: Redis 集群的键空间被分割为 16384 个槽(slot), 集群的最大节点数量也是 16384 个。每个主节点都负责处理 16384 个哈希槽的其中一部分。当我们说一个集群处于“稳定”(stable)状态时, 指的是集群没有在执行重配置(reconfiguration)操作, 每个哈希槽都只由一个节点进行处理。

所以我们可以根据要插入的key知道这个key所对应的槽的号码, 再通过这个槽的号码从集群中找到对应Jedis. 具体实现如下

//初始化得到了jedis cluster, 如何获取HostAndPort集合代码就不写了

Set<HostAndPort> nodes = .....

JedisCluster jedisCluster = new JedisCluster(nodes);

Map<String, JedisPool> nodeMap = jedisCluster.getClusterNodes();

String anyHost = nodeMap.keySet().iterator().next();

//getSlotHostMap方法在下面有

TreeMap<Long, String> slotHostMap = getSlotHostMap(anyHost); 
    private static TreeMap<Long, String> getSlotHostMap(String anyHostAndPortStr) {
        TreeMap<Long, String> tree = new TreeMap<Long, String>();
        String parts[] = anyHostAndPortStr.split(":");
        HostAndPort anyHostAndPort = new HostAndPort(parts[0], Integer.parseInt(parts[1]));
        try{
            Jedis jedis = new Jedis(anyHostAndPort.getHost(), anyHostAndPort.getPort());
            List<Object> list = jedis.clusterSlots();
            for (Object object : list) {
                List<Object> list1 = (List<Object>) object;
                List<Object> master = (List<Object>) list1.get(2);
                String hostAndPort = new String((byte[]) master.get(0)) + ":" + master.get(1);
                tree.put((Long) list1.get(0), hostAndPort);
                tree.put((Long) list1.get(1), hostAndPort);
            }
            jedis.close();
        }catch(Exception e){

        }
        return tree;
    }
上面这几步可以在初始化的时候就完成. 不需要每次都调用, 把nodeMap和slotHostMap都定义为静态变量.
//获取槽号

int slot = JedisClusterCRC16.getSlot(key); 

//获取到对应的Jedis对象

Map.Entry<Long, String> entry = slotHostMap.lowerEntry(Long.valueOf(slot));

Jedis jedis = nodeMap.get(entry.getValue()).getResource();

建议上面这步操作可以封装成一个静态方法, 比如命名为public static Jedis getJedisByKey(String key) 之类的. 意思就是在集群中, 通过key获取到这个key所对应的Jedis对象.

这样再通过上面的jedis.pipelined();来就可以进行批量插入了.

注:这个方法是从Google上搜来的, 直到目前我使用起来还没发现什么问题. 如果哪位大神发现有什么不对的地方欢迎提出来.

时间: 2024-08-30 06:24:47

在Redis集群中使用pipeline批量插入的相关文章

Redis集群中,是选择奇数节点还是偶数节点?(理论)

我们来通过一组组示例进行分析: 3节点环境:1个master.2个slave 存储空间:最大等于1个节点的容量.(如果是2个master的话,那么数据会丢失一部分) 冗余性:允许1个节点故障. 4节点环境:2个master.2个slave 存储空间:2个节点的容量. 冗余性:允许1个节点故障.(集群中,半数以上节点认为故障,才会选举.) 5节点环境:2个master.3个slave 存储空间:2个节点的容量. 冗余性:允许2个节点故障. 6节点环境:3个master.3个slave 存储空间:3

Redis集群中删除/修改节点(master、slave)(实验)

删除一个slave节点: # redis-trib.rb del-node 192.168.2.202:6380 e4dc23dc67418bf66c6c63655110612cb9516aff // del-node  host:port  node-id >>> Removing node e4dc23dc67418bf66c6c63655110612cb9516aff from cluster 192.168.2.202:6380 >>> Sending CLUS

如何确定Redis集群中各个节点的主从关系

1.首先通过命令(以192.168.203.141为例,-c代表集群的意思) ./redis-cli -h 192.168.203.141 -p 8001 -c 2.然后在输入  cluster nodes 命令,然后就会显示出各个节点的主从信息了 原文地址:https://www.cnblogs.com/fengzifengfeng/p/10421431.html

redis集群(jedis)批量删除同一前缀

public Set<String> getByPrefix(String key) { Set<String> setResult = new HashSet<>(); try { ShardedJedis jedis = redisDataSource.getJedisClient(); Iterator<Jedis> jedisIterator = jedis.getAllShards().iterator(); while(jedisIterator

Redis3.0集群crc16算法php客户端实现方法(php取得redis3.0集群中redis数据所在的redis分区插槽,并根据分区插槽取得分区所在redis服务器地址)

数据分区        Redis集群将数据分区后存储在多个节点上,即不同的分区存储在不同的节点上,每个节点可以存储多个分区.每个分区在Redis中也被称为"hash slot",Redis集群中总共规划了16384个分区. 例如:当集群中有3个节点时,节点A将包含0-5460分区,节点B将包含5461-10922分区,节点C将包含10923-16383分区. 每个key将会存储到一个唯一的分区中,每个分区其实就是一组key的集合,两者对应关系为:key的CRC16校验码%16384=

redis集群批量删除指定的key

1.说明 redis集群上有时候会需要删除多个key,就必须需要登录到每个节点上,而且有可能这个key不在这个节点,这样删除起来就比较麻烦,下面提供一种便捷方式可以实现 2.查看redis集群中的master节点 首先你要确认有哪几台master节点,可以用下面命令查看: #./redis-cli  cluster nodes | grep master PS:在这里我有3台master主节点,端口都是6379 3.编写redis_del.sh脚本 #!/bin/bash redis_comm=

redis.conf中bind绑定IP不对,redis集群创建节点的时候,报错|redi群集密码设置

前言# 我们都知道,redis 的配置文件中,默认绑定接口是 127.0.0.1,也就是本地回环接口,所以是无法从外网连接 redis 服务的.如果想要让外网也能连接使用服务器上的 redis 服务,可以简单地注释掉 bind 这一行.但对于 bind 参数的作用,网上有很多文章的解释都是误人子弟的. 关于bind# 翻看网上的文章,此处多翻译为: 指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求,在生产环境中最好设置该项.这种解释会搞糊涂初学者,甚至是错误

Redis集群批量操作

Redis在3.0版正式引入了集群这个特性,扩展变得非常简单.然而当你开心的升级到3.0后,却发现有些很好用的功能现在工作不了了, 比如我们今天要聊的pipeline功能等批量操作. Redis集群是没法执行批量操作命令的,如mget,pipeline等.这是因为redis将集群划分为16383个哈希槽,不同的key会划分到不同的槽中.但是,Jedis客户端提供了计算key的slot方法,已经slot和节点之间的映射关系,通过这两个数据,就可以计算出每个key所在的节点,然后使用pipeline

redis 集群搭建

redis集群配置 1.1 介绍 redisCluster: 在3.0版本以后支持,无中心,在某种情况下会造成数据丢失,其也是通过算法将数据分片保存至某个redis服务器,即不再通过客户端计算key保存的redis服务器,redis服务器需要提前设置好自己所负责的槽位,比如redis A负责处理0-5000的哈希槽位数据,redis B负责处理5001-10000的hash槽位数据,redis C负责处理10001-16384的hash槽位数据,redis cluster需要特定的客户端,要求客