通过对 key 做哈希,来实现 Redis 服务器的分片。
用这个例子来演示这个小库的用法:
package main
import (
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"time"
"github.com/go-redis/redis"
"github.com/serialx/hashring"
)
func RandomString(length int) (string, error) {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(b)[:length], nil
}
func main() {
redisServers := map[string]int{
"redis1:6379": 200,
"redis2:6379": 100,
}
redisClients := []*redis.Client{}
for uri, _ := range redisServers {
redisClients = append(redisClients, redis.NewClient(&redis.Options{Addr: uri}))
}
log.Println(redisServers)
ring := hashring.NewWithWeights(redisServers)
stat := map[string]int{}
for uri, _ := range redisServers {
stat[uri] = 0
}
for i := 0; i < 100; i++ {
randstr, _ := RandomString(8)
key := "test:randkey:" + randstr
node, ok := ring.GetNode(key)
if !ok {
log.Panicf("cannot assign a redis client by key: %#v", key)
}
log.Printf("%s -> %s", key, node)
stat[node]++
var client *redis.Client
for _, _client := range redisClients {
if node == _client.Options().Addr {
client = _client
break
}
}
if client == nil {
log.Panicf("redis client assigned error: %#v", node)
}
client.Set(key, 1, time.Minute)
}
fmt.Println(stat)
}