说明
在上篇博文《Redis学习(二):redis集群之cluster模式下的跨节点的批量操作 I》中,对Jedis客户端的JedisCluster类源码进行了学习,了解了Jedis对cluster操作原理,其中有两个关键类JedisClusterConnectionHandler和JedisClusterInfoCache,在JedisClusterInfoCache类中有两个关键变量Map<String,JedisPool> nodes 和 Map<Integer, JedisPool> slots,这两个变量主要存储了cluster集群的主节点信息和其负责的槽点信息。在网上的资料查询资料后发现,对redis cluster进行批量操作主要以pipeline的方式实现。
本篇博文将结合之前学习源码获取的知识和pipeline的方式,实现cluster模式下的跨节点批量操作。这里主要是通过对key进行区分,以通过CRC16算法获取的slot所在同一个节点的key进行区分,然后分别通过pipeline方式获取后,再进行聚合返回。所以代码中如何获取slot所对应的Jedis则成为关键步骤。
这里总结两种方式,一种是通过反射从JedisCluster类中获取connectionHandler对象属性,再通过此对象以反射方式获取cache对象属性,通过cache的slots变量获取对应的JedisPool进行分类。另外一种方式则是通过JedisCluster对象的getClusterNodes()获取集群节点的信息,然后通过TreeMap<Long, String> map将主节点负责的槽点位置进行存储,通过slot获取节点信息来获取JedisPool。
以上两种方式本质上没有区别,都是以key的slot值得到对应的节点的JedisPool方式将key进行分类,主要是在获取JedisPool的方式上有所差别。
正文
反射
创建RedisClusterManager类,该类有以下变量:
public static final String NODES_ADDR = "";
private static final JedisCluster cluster;
private static final Field CONNECTION_HANDLER;
private static final Field CACHE_INFO;
private static final JedisSlotBasedConnectionHandler connectionHandler;
private static final JedisClusterInfoCache clusterInfoCache;
通过类对象和变量名称获取类的变量对象Field,再通过反射获取其值。关键代码为:
CONNECTION_HANDLER = getField(BinaryJedisCluster.class, "connectionHandler");
CACHE_INFO = getField(JedisClusterConnectionHandler.