创建redisClient BinaryJedisCluster
我们可以从jedis给出官方的redis-clusterdemo上可以看到通过构造一个BinaryJedisCluster,这个类就是jedis给我们提供的一个与redis-cluster集群交互的一个基本接口类,有了这个类我们就能执行各种查询写入操作了。
- 我们从BinaryJedisCluster的构造函数一路debug下去,可以看到这个类有一个JedisClusterConnectionHandler成员变量,在该类的构造函数当中,会去给这个成员变量赋值。进而会调用JedisSlotBasedConnectionHandler类的构造方法,又会调用到父类的构造方法。
- JedisClusterConnectionHandler类中有一个JedisClusterInfoCache成员变量,在该类的构造函数中,会给JedisClusterInfoCache初始化。JedisSlotBasedConnectionHandler这个类是该类的子类,实现了抽象父类的getConnection,getConnectionFromSlot(int)两个方法。
- JedisClusterInfoCache这个类缓存了redis集群的集群分片信息,我们下面来看下。
|
|
可以看到,JedisClusterInfoCache的discoverClusterNodesAndSlots方法通过任意一个jedis实例然后调用jedis.clusterSlots()拿到redis集群分配的slot信息,然后把slot信息以及hostinfo信息缓存到两个对应的JedisPool map里面,这样启动阶段基本完成了。
通过BinaryJedisCluster与redis-cluster交互
我们通过以下代码入手
上述通过一个简单的get操作,最终会调用到BinaryJedisCluster.runBinary(key)方法。
- 正常情况:上述代码connection=connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));这个是根据key来计算对应的slot,然后根据启动阶段JedisClusterInfoCache的private final Map
slots = new HashMap ()属性来找到该slot对应的JedisPool,然后从pool中获取一个jedis connection,最终执行connection.get(key); - 异常情况1:JedisNoReachableClusterNodeException,显然都没有可以访问的节点了,直接向上层抛出,不做处理。
- 异常情况2:JedisConnectionException会进行重试,如果当前已经是最后一次重试,则this.connectionHandler.renewSlotCache()更新slotcache。
- 异常情况3:JedisRedirectionException和异常情况2差不多基本也是更新slot,不同是此时jedis是通的,所以可以直接传进renewSlotCache(jedis),避免renewSlotCache方法内部多余的轮询获取jedis的操作。然后重试。