Jedis源码分析(四) - JedisSentinel与ShardedJedis介绍

Jedis源码分析共有四个章节,以下为各章链接:

  1. Jedis源码分析(一) - Jedis介绍
  2. Jedis源码分析(二) - Jedis类结构及实现
  3. Jedis源码分析(三) - JedisCluster类结构及实现
  4. Jedis源码分析(四) - JedisSentinel与ShardedJedis介绍

JedisSentinel

JedisSentinel常用方式有两种:

1.使用哨兵单节点拿到主节点,从节点的信息

1
2
3
4
5
6
7
8
9
//通过哨兵节点的信息新建Jedis实例,然后拿到Master节点的信息
Jedis j = new Jedis(sentinel);
List<Map<String, String>> masters = j.sentinelMasters();
//拿到master的address,**MASTER_NAME**
List<String> masterHostAndPort = j.sentinelGetMasterAddrByName(**MASTER_NAME**);
HostAndPort masterFromSentinel = new HostAndPort(masterHostAndPort.get(0),Integer.parseInt(masterHostAndPort.get(1)));
assertEquals(master, masterFromSentinel);
//通过哨兵节点,拿到从节点的信息
List<Map<String, String>> slaves = j.sentinelSlaves(**MASTER_NAME**);

2.使用哨兵节点对象池

1
2
3
4
5
Set<String> sentinels = new HashSet<String>();
sentinels.add(new HostAndPort("localhost", 65432).toString());
sentinels.add(new HostAndPort("localhost", 65431).toString());
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels);
pool.destroy();

JedisSentinelPool的结构清晰,内部使用对象池存放一个个sentinel实例。图2-12和2-13分别为JedisSentinelPool的类结构和初始化流程。在使用时,我们先根据,host,port等信息,初始化一个Jedis实例,然后可以通过sentinelMasters()sentinelGetMasterAddrByName(MASTER_NAME)sentinelSlaves(MASTER_NAME)等方法拿到这个哨兵节点监听的MASTER节点信息或对应的SLAVE节点信息。

image014

图1.1 JedisSentinelPool 的类结构

image015

图1.2 JedisSentinelPool 的初始化流程

ShardedJedis

下文为构建Jedis分片的方法(单节点与对象池的模式),

1.单节点模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(2);
//其中一个分片
JedisShardInfo shard1 = new JedisShardInfo(redis1);
shards.add(shard1);
//另一个分片
JedisShardInfo shard2 = new JedisShardInfo(redis2);
shards.add(shard2);
@SuppressWarnings("resource")
//新建ShardedJedis实例
ShardedJedis shardedJedis = new ShardedJedis(shards);
shardedJedis.set("a", "bar");
//通过key可以查看存储在哪个jedis
JedisShardInfo ak = shardedJedis.getShardInfo("a");
assertEquals(shard2, ak);

2.对象池模式

1
2
3
4
ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);
ShardedJedis jedis = pool.getResource();
jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));

image016

图2-1 ShardedJedis的类结构

image017

图2-1 ShardedJedis的初始化流程

图2-1为ShardedJedis的类结构(其内部保存一个对象池,与常规的JedisPool的不同之处在于,内部的PooledObjectFactory实现不同),分片信息保存在基类Sharded中,Sharded保存了3个重要变量:

  1. nodes是一个TreeMap,保存了每个分片节点和对应的hash值。
  2. algo是计算hash值的函数,默认是MurmurHash,可替换。
  3. resources是一个LinkedHashMap,存放着JedisShardinfo和一个Jedis实例的对应关系。

图2-2为 ShardedJedis的初始化流程,通过传入待分片的节点信息,初始化好上述3个变量。在使用时,先根据key计算出hash值,在nodes中找到对应的分片信息,再在resources中找到对应的Jedis实例,然后通过这个Jedis实例才操作redis节点。

0%