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

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

  1. /**
  2. * 根据key计算slot,
  3. * 再根据slot计算node,
  4. * 获取pipeline
  5. * 进行批量操作
  6. */
  7. public class BatchUtil {
  8. public static Map<String, String> mget(JedisCluster jc, String... keys){
  9. Map<String, String> resMap = new HashMap<>();
  10. if(keys == null || keys.length == 0){
  11. return resMap;
  12. }
  13. //如果只有一条,直接使用get即可
  14. if(keys.length == 1){
  15. resMap.put(keys[0], jc.get(keys[0]));
  16. return resMap;
  17. }
  18.  
  19. //JedisCluster继承了BinaryJedisCluster
  20. //BinaryJedisCluster的JedisClusterConnectionHandler属性
  21. //里面有JedisClusterInfoCache,根据这一条继承链,可以获取到JedisClusterInfoCache
  22. //从而获取slot和JedisPool直接的映射
  23. MetaObject metaObject = SystemMetaObject.forObject(jc);
  24. JedisClusterInfoCache cache = (JedisClusterInfoCache) metaObject.getValue("connectionHandler.cache");
  25. //保存地址+端口和命令的映射
  26. Map<JedisPool, List<String>> jedisPoolMap = new HashMap<>();
  27. List<String> keyList = null;
  28. JedisPool currentJedisPool = null;
  29. Pipeline currentPipeline = null;
  30.  
  31. for(String key : keys){
  32. //计算哈希槽
  33. int crc = JedisClusterCRC16.getSlot(key);
  34. //通过哈希槽获取节点的连接
  35. currentJedisPool = cache.getSlotPool(crc);
  36. //由于JedisPool作为value保存在JedisClusterInfoCache中的一个map对象中,每个节点的
  37. //JedisPool在map的初始化阶段就是确定的和唯一的,所以获取到的每个节点的JedisPool都是一样
  38. //的,可以作为map的key
  39. if(jedisPoolMap.containsKey(currentJedisPool)){
  40. jedisPoolMap.get(currentJedisPool).add(key);
  41. }else{
  42. keyList = new ArrayList<>();
  43. keyList.add(key);
  44. jedisPoolMap.put(currentJedisPool, keyList);
  45. }
  46. }
  47.  
  48. //保存结果
  49. List<Object> res = new ArrayList<>();
  50. //执行
  51. for(Entry<JedisPool, List<String>> entry : jedisPoolMap.entrySet()){
  52. try {
  53. currentJedisPool = entry.getKey();
  54. keyList = entry.getValue();
  55. //获取pipeline
  56. currentPipeline = currentJedisPool.getResource().pipelined();
  57. for(String key : keyList){
  58. currentPipeline.get(key);
  59. }
  60. //从pipeline中获取结果
  61. res = currentPipeline.syncAndReturnAll();
  62. currentPipeline.close();
  63. for(int i=0; i<keyList.size(); i++){
  64. resMap.put(keyList.get(i), res.get(i)==null ? null : res.get(i).toString());
  65. }
  66. } catch (Exception e) {
  67. e.printStackTrace();
  68. return new HashMap<>();
  69. }
  70. }
  71. return resMap;
  72. }
  73. }

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. sublime插件insertDate显示ISO时间

    1 下载insertDate插件以及安装完毕 2 把光标放在想插入ISO时间的地方 3 按住:alt+f5,之后,在sublime下面的Date format string输入:iso.之后按ente ...

  2. 使用EA完成数据库设计

    开始重构之后对于EA的了解也逐渐增多,今天就总结一下如何使用EA完成对数据库的设计.下边的图分别是截自机房收费系统和牛腩新闻开发的数据库,因为我第一遍写的时候是在机房合作的时候,而后建立牛腩新闻发布系 ...

  3. C++ std::pair

    pair是将2个数据组合成一个数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存.另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair. ...

  4. Python之文件输入输出,

      文件输入与输出 • 打开文件返回文件对象 – file_object=open(file_name,access_mode='r') • 关闭文件对象 – file_object.close() ...

  5. 如何解决WAMP Server 与IIS端口冲突问题

    PHP也是一门开发网页的语言,WAMP Server 是它的一个较好的集成开发环境,今日,小编发现好多Wamp Server 安装后启动local host 出现的却是IIS页面!为什么会这样呢? 出 ...

  6. C#生成满足特定要求的密码

    代码1 Random m_rnd = new Random(); public char getRandomChar() { ); || (ret > && ret < ) ...

  7. 超级实用的Chrome插件

    1.JSON-handle:浏览器前台访问后台,后台返回json,它帮你格式化 2.Page Ruler:帮你测量页面上任何位置的长宽高 3. Momentum:打开新的tab页就像打开了一个新的世界 ...

  8. 网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法:

    转载自网络,非原创 1.输出语句:document.write(""); 2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head ...

  9. C++11之lambda表达式解析

    什么是Lanmbda? 简短函数,就地书写.常用于向函数(算法)传递函数参数. 语法 Lambda 表达式,[capture](paras)mutable->return type{statem ...

  10. pandas基础(2)_多重索引

    1:多重索引的构造 >>> #下面显示构造pd.MultiIndex >>> df1=DataFrame(np.random.randint(0,150,size= ...