Example #1
0
func makeClusters(
	redisInstances string,
	connectTimeout, readTimeout, writeTimeout time.Duration,
	redisMCPI int,
	hashFunc func(string) uint32,
	maxSize int,
	instr instrumentation.Instrumentation,
) ([]cluster.Cluster, error) {
	clusters := []cluster.Cluster{}
	for i, clusterInstances := range strings.Split(redisInstances, ";") {
		addresses := stripBlank(strings.Split(clusterInstances, ","))
		if len(addresses) <= 0 {
			continue
		}
		clusters = append(clusters, cluster.New(
			pool.New(
				addresses,
				connectTimeout, readTimeout, writeTimeout,
				redisMCPI,
				hashFunc,
			),
			maxSize,
			instr,
		))
		log.Printf("Redis cluster %d: %d instance(s)", i+1, len(addresses))
	}
	if len(clusters) <= 0 {
		return []cluster.Cluster{}, fmt.Errorf("no cluster(s)")
	}
	return clusters, nil
}
Example #2
0
// ParseFarmString parses a farm declaration string into a slice of clusters.
// A farm string is a semicolon-separated list of cluster strings. A cluster
// string is a comma-separated list of Redis instances. All whitespace is
// ignored.
//
// An example farm string is:
//
//  "foo1:6379, foo2:6379; bar1:6379, bar2:6379, bar3:6379, bar4:6379"
//
func ParseFarmString(
	farmString string,
	connectTimeout, readTimeout, writeTimeout time.Duration,
	redisMCPI int,
	hash func(string) uint32,
	maxSize int,
	selectGap time.Duration,
	instr instrumentation.Instrumentation,
) ([]cluster.Cluster, error) {
	var (
		seen     = map[string]int{}
		clusters = []cluster.Cluster{}
	)
	for i, clusterString := range strings.Split(stripWhitespace(farmString), ";") {
		hostPorts := []string{}
		for _, hostPort := range strings.Split(clusterString, ",") {
			if hostPort == "" {
				continue
			}
			toks := strings.Split(hostPort, ":")
			if len(toks) != 2 {
				return []cluster.Cluster{}, fmt.Errorf("invalid host-port %q", hostPort)
			}
			if _, err := strconv.ParseUint(toks[1], 10, 16); err != nil {
				return []cluster.Cluster{}, fmt.Errorf("invalid port %q in host-port %q (%s)", toks[1], hostPort, err)
			}
			seen[hostPort]++
			hostPorts = append(hostPorts, hostPort)
		}
		if len(hostPorts) <= 0 {
			return []cluster.Cluster{}, fmt.Errorf("empty cluster %d (%q)", i+1, clusterString)
		}
		clusters = append(clusters, cluster.New(
			pool.New(hostPorts, connectTimeout, readTimeout, writeTimeout, redisMCPI, hash),
			maxSize,
			selectGap,
			instr,
		))
		log.Printf("cluster %d: %d instance(s)", i+1, len(hostPorts))
	}

	if len(clusters) <= 0 {
		return []cluster.Cluster{}, fmt.Errorf("no clusters specified")
	}

	duplicates := []string{}
	for hostPort, count := range seen {
		if count > 1 {
			duplicates = append(duplicates, hostPort)
		}
	}
	if len(duplicates) > 0 {
		return []cluster.Cluster{}, fmt.Errorf("duplicate instances found: %s", strings.Join(duplicates, ", "))
	}

	return clusters, nil
}
Example #3
0
func newFarm(
	redisInstances string,
	writeQuorumStr string,
	connectTimeout, readTimeout, writeTimeout time.Duration,
	redisMCPI int,
	hash func(string) uint32,
	readStrategy farm.ReadStrategy,
	repairStrategy farm.RepairStrategy,
	maxSize int,
	statsdSampleRate float64,
	bucketPrefix string,
) (*farm.Farm, error) {
	// Build instrumentation.
	instr := statsd.New(stats, float32(statsdSampleRate), bucketPrefix)

	// Parse out and build clusters.
	clusters := []cluster.Cluster{}
	for i, clusterInstances := range strings.Split(redisInstances, ";") {
		addresses := stripBlank(strings.Split(clusterInstances, ","))
		if len(addresses) <= 0 {
			continue
		}
		clusters = append(clusters, cluster.New(
			pool.New(
				addresses,
				connectTimeout, readTimeout, writeTimeout,
				redisMCPI,
				hash,
			),
			maxSize,
			instr,
		))
		log.Printf("Redis cluster %d: %d instance(s)", i+1, len(addresses))
	}
	if len(clusters) <= 0 {
		return nil, fmt.Errorf("no cluster(s)")
	}

	// Evaluate writeQuorum.
	writeQuorum, err := evaluateScalarPercentage(writeQuorumStr, len(clusters))
	if err != nil {
		return nil, err
	}

	// Build and return Farm.
	return farm.New(
		clusters,
		writeQuorum,
		readStrategy,
		repairStrategy,
		instr,
	), nil
}
Example #4
0
func integrationCluster(t *testing.T, addresses string, maxSize int) cluster.Cluster {
	p := pool.New(
		strings.Split(addresses, ","),
		1*time.Second, // connect timeout
		1*time.Second, // read timeout
		1*time.Second, // write timeout
		10,            // max connections per instance
		pool.Murmur3,  // hash
	)

	for i := 0; i < p.Size(); i++ {
		p.WithIndex(i, func(conn redis.Conn) error {
			_, err := conn.Do("FLUSHDB")
			if err != nil {
				t.Fatal(err)
			}
			return nil
		})
	}

	return cluster.New(p, maxSize, nil)
}