Redis应用学习总结(二)-sharejedis源码分析

分片链接sharejedis的流程源码分析:

创建sharejedis有两种方法,一个是通过池的方式shardedJedisPool.getResource(),这里面底层的实现涉及到java通用池的源码分析,后续有机会再分析,先说说普通的通过构造方法创建的流程源码。

 public ShardedJedis(List shards, Hashing algo,Pattern keyTagPattern) {

   super(shards, algo, keyTagPattern);

  }

--通过上面的构造方法可以看出,创建一个sharejedis对象要传入一个JedisShardInfo列表,还有一个哈希算法Hashingalgo,Pattern keyTagPattern则为对key进行哈希的限制条件。其中后两者一般都采用默认值,主要是JedisShardInfo> shards,其中JedisShardInfo里面填充了创建redis链接需要的各种信息,比如ip,端口等,这是我们分析流程的主线,从构造方法可以看到调用了父类BinaryShardedJedis的构造方法来实现。

publicBinaryShardedJedis(List shards, Hashing algo, PatternkeyTagPattern) {

   super(shards, algo, keyTagPattern);

  }

--而BinaryShardedJedis继续调用了它的父类Sharded的构造方法实现

public Sharded(List shards,Hashing algo, Pattern tagPattern) {

   this.algo = algo;

   this.tagPattern = tagPattern;

   initialize(shards);

  }

--调用Sharded. initialize(shards);

private void initialize(Listshards) {

   nodes = new TreeMap();

 

   for (int i = 0; i != shards.size(); ++i) {

     final S shardInfo = shards.get(i);

     if (shardInfo.getName() == null) for (int n = 0; n < 160 *shardInfo.getWeight(); n++) {

       nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" +n), shardInfo);

     }

     else for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {

       nodes.put(this.algo.hash(shardInfo.getName() + "*" +shardInfo.getWeight() + n), shardInfo);

     }

     resources.put(shardInfo, shardInfo.createResource());

    }

  }

--其中nodes.put(this.algo.hash(shardInfo.getName()+ "*" + shardInfo.getWeight() + n), shardInfo);和resources.put(shardInfo,shardInfo.createResource());需重点注意,前者是往TreeMap添加键值对,也就是虚拟节点(hash(key))和shardInfo的映射关系,后者是往LinkedHashMap, R>中添加键值对,也就是shardInfo和jedis的映射关系,其中jedis由shardInfo.createResource()创建。源码如下

public Jedis createResource() {

   return new Jedis(this);

  }

-- return new Jedis(this);调用了jedis的一个重载构造方法

public Jedis(JedisShardInfo shardInfo) {

   super(shardInfo);

  }

-- Jedis调用了它的父类BinaryJedis的构造方法实现

public BinaryJedis(final JedisShardInfoshardInfo) {

   client = new Client(shardInfo.getHost(), shardInfo.getPort(),shardInfo.getSsl(),

       shardInfo.getSslSocketFactory(), shardInfo.getSslParameters(),

       shardInfo.getHostnameVerifier());

   client.setConnectionTimeout(shardInfo.getConnectionTimeout());

   client.setSoTimeout(shardInfo.getSoTimeout());

   client.setPassword(shardInfo.getPassword());

   client.setDb(shardInfo.getDb());

  }

--最终在BinaryJedis中创建了连接客户端对象client,并根据JedisShardInfo中的信息比如ip,端口,超时时长等进行了和服务端的链接工作。

当我们使用ShardedJedis对redis数据库进行读写操作时的流程如下:

Jedis jedis = shardedJedis.getShard(key);

Jedis.set(key);

Jedis.get(key);

首先,shardedJedis.getShard(key);调用了父类Sharded的源码如下

public R getShard(String key) {

   return resources.get(getShardInfo(key));

  }

--其中的resources就是前面介绍的Sharded.initialize()里面的LinkedHashMap,也就是存储着shardInfo和jedis的映射关系。而getShardInfo(key)的实现如下:

public S getShardInfo(byte[] key) {

   SortedMap tail = nodes.tailMap(algo.hash(key));

   if (tail.isEmpty()) {

     return nodes.get(nodes.firstKey());

    }

   return tail.get(tail.firstKey());

  }

--通过nodes,也就是前面介绍的Sharded.initialize()里面的TreeMap(虚拟节点(hash(key))和shardInfo的映射关系)获得hash(key)后对应的shardInfo对象,然后再通过LinkedHashMap获取shardInfo对象对应的jedis实例,然后通过这个jedis对redis进行读写操作。

而jedis的get和set操作的源码如下:

public String get(final String key) {

   checkIsInMultiOrPipeline();

   client.sendCommand(Protocol.Command.GET, key);

   return client.getBulkReply();

  }

public String set(final String key, Stringvalue) {

   checkIsInMultiOrPipeline();

   client.set(key, value);

   return client.getStatusCodeReply();

  }

用了父类BinaryJedis类中的链接客户端对象client属性进行读写操作。这样一来不但把ShardedJedis的使用流程的源码分析了一遍,也顺便把普通的jedis的操作底层源码分析了一遍。

         整个ShardedJedis创建和使用流程如上所述。简单来说就是创建时创建了两个容器TreeMap和LinkedHashMap,应用时又通过这两个容器找到key对应的jedis对象进行操作。

你可能感兴趣的:(大数据,redis,sharejedis)