func (r *RedisRing) Close() error {
	var err error
	for _, client := range r.clients {
		err = client.Close()
	}
	return err
}
Close all clients in the ring
package redisfs
import (
	"errors"
	"fmt"
	"strings"
	"github.com/cea-hpc/pdwfs/config"
	"github.com/cea-hpc/pdwfs/redigo/redis"
	"github.com/cea-hpc/pdwfs/util"
)
var (
	ErrRedisKeyNotFound = errors.New("Redis key not found")
)
func Try(err error) {
	if err != nil {
		panic(err)
	}
}
var Check = Try
func err(a interface{}, err error) error {
	return err
}
type RedisClient struct {
	pool *redis.Pool
}
func NewRedisClient(addr string) *RedisClient {
	return &RedisClient{
		pool: &redis.Pool{
			MaxIdle:     5,
			MaxActive:   50,    
			Wait:        true,  
			IdleTimeout: 0,
			Dial: func() (redis.Conn, error) {
				return redis.Dial("tcp", addr)
			},
		},
	}
}
func (c *RedisClient) Close() error {
	return c.pool.Close()
}
func (c *RedisClient) SetRange(key string, offset int64, data []byte) error {
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("SETRANGE", key, offset, data))
}
func (c *RedisClient) GetRange(key string, start, end int64) ([]byte, error) {
	conn := c.pool.Get()
	defer conn.Close()
	b, err := redis.Bytes(conn.Do("GETRANGE", key, start, end))
	if err == redis.ErrNil {
		return b, ErrRedisKeyNotFound
	}
	return b, err
}
func (c *RedisClient) GetRangeInto(key string, start, end int64, dst []byte) (int, error) {
	conn := c.pool.Get()
	defer conn.Close()
	conn.SetReadBuffer(dst)
	defer conn.UnsetReadBuffer()
	read, err := redis.ReadBytes(conn.Do("GETRANGE", key, start, end))
	if err == redis.ErrNil {
		return 0, ErrRedisKeyNotFound
	}
	return read, err
}
func (c *RedisClient) Exists(key string) (bool, error) {
	conn := c.pool.Get()
	defer conn.Close()
	return redis.Bool(conn.Do("EXISTS", key))
}
func (c *RedisClient) Set(key string, data []byte) error {
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("SET", key, data))
}
func (c *RedisClient) SetNX(key string, data []byte) error {
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("SETNX", key, data))
}
func (c *RedisClient) Get(key string) ([]byte, error) {
	conn := c.pool.Get()
	defer conn.Close()
	b, err := redis.Bytes(conn.Do("GET", key))
	if err == redis.ErrNil {
		return b, ErrRedisKeyNotFound
	}
	return b, err
}
func (c *RedisClient) Strlen(key string) (int, error) {
	conn := c.pool.Get()
	defer conn.Close()
	l, err := redis.Int(conn.Do("STRLEN", key))
	if err == redis.ErrNil {
		return l, ErrRedisKeyNotFound
	}
	return l, err
}
func (c *RedisClient) GetInto(key string, dst []byte) (int, error) {
	conn := c.pool.Get()
	defer conn.Close()
	conn.SetReadBuffer(dst)
	defer conn.UnsetReadBuffer()
	read, err := redis.ReadBytes(conn.Do("GET", key))
	if err == redis.ErrNil {
		return 0, ErrRedisKeyNotFound
	}
	return read, err
}
func (c *RedisClient) Unlink(keys ...string) error {
	k := make([]interface{}, len(keys))
	for i, v := range keys {
		k[i] = v
	}
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("UNLINK", k...))
}
func (c *RedisClient) SAdd(key string, member string) error {
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("SADD", key, member))
}
func (c *RedisClient) SRem(key string, member string) error {
	conn := c.pool.Get()
	defer conn.Close()
	return err(conn.Do("SREM", key, member))
}
func (c *RedisClient) SMembers(key string) ([]string, error) {
	conn := c.pool.Get()
	defer conn.Close()
	return redis.Strings(conn.Do("SMEMBERS", key))
}
type Pipe struct {
	conn redis.Conn
}
func (p Pipe) Do(cmd string, args ...interface{}) {
	Try(p.conn.Send(cmd, args...))
}
func (p Pipe) Flush() {
	defer p.conn.Close()
	_, err := p.conn.Do("EXEC")
	Check(err)
}
func (c *RedisClient) Pipeline() *Pipe {
	conn := c.pool.Get()
	conn.Send("MULTI")
	return &Pipe{conn}
}
type RedisRing struct {
	clients map[string]*RedisClient
	hash    *util.ConsistentHash
}
func NewRedisRing(conf *config.Redis) *RedisRing {
	ids := make([]string, len(conf.Addrs))
	clients := make(map[string]*RedisClient)
	for i, addr := range conf.Addrs {
		ids[i] = fmt.Sprintf("%d", i)
		clients[ids[i]] = NewRedisClient(addr)
	}
	hash := util.NewConsistentHash(100, nil)
	hash.Add(ids...)
	return &RedisRing{
		clients: clients,
		hash:    hash,
	}
}
func (r *RedisRing) GetClient(key string) *RedisClient {
	k := key
	if s := strings.IndexByte(key, '{'); s > -1 {
		if e := strings.IndexByte(key[s+1:], '}'); e > 0 {
			k = key[s+1 : s+e+1]
		}
	}
	return r.clients[r.hash.Get(k)]
}