1 JedisShardInfo 默认不支持选择数据库
扩展后的代码
package redis.clients.jedis.ext;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
public class JedisDBShardInfo extends JedisShardInfo {
private int database;
public JedisDBShardInfo(String host,int database) {
super(host, 6379);
this.database=database;
}
public JedisDBShardInfo(String host, String name,int database) {
super(host, 6379, name);
this.database=database;
}
public JedisDBShardInfo(String host, int port,int database) {
super(host, port, 2000);
this.database=database;
}
public JedisDBShardInfo(String host, int port, String name,int database) {
super(host, port, 2000, name);
this.database=database;
}
public JedisDBShardInfo(String host, int port, int timeout,int database) {
super(host, port, timeout, 1);
this.database=database;
}
public JedisDBShardInfo(String host, int port, int timeout, String name,int database) {
super(host, port, timeout, name);
this.database=database;
}
public Jedis createResource() {
Jedis jedis=new Jedis(this);
try {
if (this.database != 0&&jedis.ping().equals("PONG")) {
jedis.select(this.database);
return jedis;
}
} catch (Exception e) {
System.out.println("连接异常=>"+getHost()+":"+getPort()+":"+getDatabase());
//e.printStackTrace();
}
return null;
}
public int getDatabase() {
return database;
}
public void setDatabase(int database) {
this.database = database;
}
}
2 目前发现,当分片的时候,只要其中一台服务器出现问题,导致所有的分片jedis都无法使用,没法实现动态的将故障服务器暂时的过滤到,修改了源代码
package redis.clients.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Sharded<R, S extends ShardInfo<R>> {
public static final int DEFAULT_WEIGHT = 1;
private TreeMap<Long, S> nodes;
private final Hashing algo;
private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();
/**
* The default pattern used for extracting a key tag. The pattern must have
* a group (between parenthesis), which delimits the tag to be hashed. A
* null pattern avoids applying the regular expression for each lookup,
* improving performance a little bit is key tags aren't being used.
*/
private Pattern tagPattern = null;
// the tag is anything between {}
public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern
.compile("\\{(.+?)\\}");
public Sharded(List<S> shards) {
this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works
// with 64-bits not 128
}
public Sharded(List<S> shards, Hashing algo) {
this.algo = algo;
initialize(shards);
}
public Sharded(List<S> shards, Pattern tagPattern) {
this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good
// as we works with
// 64-bits not 128
}
public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) {
this.algo = algo;
this.tagPattern = tagPattern;
initialize(shards);
}
private void initialize(List<S> shards) {
nodes = new TreeMap<Long, S>();
for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i);
<span style="color:#999999;"> </span><span style="color:#ff9966;"> //增加动态的 结合分片扩展
R r=shardInfo.createResource();
if(r!=null){
if (shardInfo.getName() == null){
for (int n = 0; n < 128 * shardInfo.getWeight(); n++) {
nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo);
}
}
else{
for (int n = 0; n < 128 * shardInfo.getWeight(); n++) {
nodes.put(this.algo.hash(shardInfo.getName() + ":" + n), shardInfo);
}
}
resources.put(shardInfo,r);
}
}</span>
}
public R getShard(byte[] key) {
return resources.get(getShardInfo(key));
}
public R getShard(String key) {
return resources.get(getShardInfo(key));
}
public S getShardInfo(byte[] keyBytes) {
//$this->initialize();
//$ringKeys = $this->_ringKeys;
Long key = this.algo.hash(keyBytes);
List<Long> keys = new ArrayList<Long>();
keys.addAll(nodes.keySet());
int upper = keys.size() - 1;
int lower = 0;
while (lower <= upper) {
int index = (lower + upper) >> 1;
Long item = keys.get(index);
if (item > key) {
upper = index - 1;
}
else if (item < key) {
lower = index + 1;
}
else {
return nodes.get(item);
}
}
return nodes.get(keys.get(wrapAroundStrategy(upper, lower, keys.size())));
}
protected int wrapAroundStrategy(int upper, int lower, int ringKeysCount) {
return upper >= 0 ? upper : ringKeysCount - 1;
}
public S getShardInfo(String key) {
return getShardInfo(SafeEncoder.encode(getKeyTag(key)));
}
/**
* A key tag is a special pattern inside a key that, if preset, is the only
* part of the key hashed in order to select the server for this key.
*
* @see http://code.google.com/p/redis/wiki/FAQ#I
* 'm_using_some_form_of_key_hashing_for_partitioning,_but_wh
* @param key
* @return The tag if it exists, or the original key
*/
public String getKeyTag(String key) {
if (tagPattern != null) {
Matcher m = tagPattern.matcher(key);
if (m.find())
return m.group(1);
}
return key;
}
public Collection<S> getAllShardInfo() {
return Collections.unmodifiableCollection(nodes.values());
}
public Collection<R> getAllShards() {
return Collections.unmodifiableCollection(resources.values());
}
}