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;
}
}

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

  1. C# redis集群批量操作之slot计算出16384个字符串

    引入一个大家都用的到的需求来说吧. 需求:要在三主三从的redis集群,存入数据,会对数据进行批量删除操作,数据要求要在redis集群负载均衡. 思路: 1.存入数据好办 1 var connect ...

  2. Redis集群最佳实践

    今天我们来聊一聊Redis集群.先看看集群的特点,我对它的理解是要需要同时满足高可用性以及可扩展性,即任何时候对外的接口都要是基本可用的并具备一定的灾备能力,同时节点的数量能够根据业务量级的大小动态的 ...

  3. redis 集群配置实战

    文章转载自:http://hot66hot.iteye.com/blog/2050676 最近研究Redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 rele ...

  4. redis集群讨论

    一.生产应用场景 二.存储架构演变 三.应用最佳实践 四.运维经验总结 第1.2节:介绍redis cluster在唯品会的生产应用场景,以及存储架构的演变.第3节:redis cluster的稳定性 ...

  5. Couchbase集群和Redis集群解析

    Couchbase集群和Redis集群解析 首先,关于一些数据库或者是缓存的集群有两种结构,一种是Cluster;一种是master-salve. 关于缓存系统一般使用的就是Redis,Redis是开 ...

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

    转载自http://blog.csdn.net/sweetvvck/article/details/38315149?utm_source=tuicool 要搭建Redis集群,首先得考虑下面的几个问 ...

  7. 【原创】那些年用过的Redis集群架构(含面试解析)

    引言 今天是2019年2月12号,也就是大年初八,我接到了高中同学刘有码面试失利的消息. 他面试的时候,身份是某知名公司的小码农一枚,却因为不懂自己生产上Redis是如何部署的,导致面试失败! 人间惨 ...

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

    前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 ...

  9. 那些年用过的Redis集群架构

    今天我们来谈谈Redis集群这个话题,需要说明的是本文 适合人群:不知道自己生产redis集群架构,以及对Redis集群不了解的人 不适合群: 对自己生产Redis集群架构非常了解的人 本文预计分两个 ...

随机推荐

  1. Codeforces 756C Nikita and stack

    Codeforces 756C Nikita and stack 题目大意: 给定一个对栈进行操作的操作序列,初始时序列上没有任何操作,每一次将一个本来没有操作的位置变为某一操作(push(x),po ...

  2. 【Lintcode】382.Triangle Count

    题目: Given an array of integers, how many three numbers can be found in the array, so that we can bui ...

  3. python爬虫知识点总结(九)Requests+正则表达式爬取猫眼电影

    一.爬取流程 二.代码演示 #-*- coding: UTF-8 -*- #_author:AlexCthon #mail:alexcthon@163.com #date:2018/8/3 impor ...

  4. 自己实现的vector

    #include <iostream> #include <memory> using std::cout; using std::endl; using std::alloc ...

  5. 洛谷P3372线段树模板1——线段树

    题目:https://www.luogu.org/problemnew/show/P3372 线段树模板. 代码如下: #include<iostream> #include<cst ...

  6. 安装pillow

    最近想学Python的图像操作.首要任务就是安装pillow.这个强大的图形处理工具. 但是我遇到了一个问题. Collecting pilow  Could not find a version t ...

  7. SynEdit(Delphi XE7)的安装和基本使用

    一.花絮 delphi自带的memo显示sql语句看的太累人了,今天决定美化一下.最起码要有“语法着色”.“显示行号”这2个功能. 意外发现了 SynEdit 控件. SynEdit是一个免费的文字编 ...

  8. Git的使用 强制放弃本地所有修改,获取master中最新版本更新本地

    git fetch --all git reset --hard origin/master git fetch --all 的意思是,下载远程库的所有内容,但不与本地做任何合并 git reset ...

  9. 使用VSTO写的一个工作证打印软件

    转行做HR近2年.最近公司要做工牌,工牌上要打印照片,姓名,工号和部门等信息.一共1000多人,如果手工排版手工打印的话,估计要死人. 于是coding的老毛病又犯了,想写个程序来打印工牌.还是拿最近 ...

  10. 使用 Addr2line 将函数地址解析为函数名

    用 Addr2line 将函数地址解析为函数名 原文链接:http://www.ibm.com/developerworks/cn/linux/l-graphvis/ Addr2line 工具(它是标 ...