jredis分片选择数据库且支持服务器故障动态过滤

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());
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值