mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-27 02:30:52 +08:00
basic cluster mode
This commit is contained in:
92
src/cluster/cluster.go
Normal file
92
src/cluster/cluster.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/HDT3213/godis/src/config"
|
||||
"github.com/HDT3213/godis/src/db"
|
||||
"github.com/HDT3213/godis/src/interface/redis"
|
||||
"github.com/HDT3213/godis/src/lib/consistenthash"
|
||||
"github.com/HDT3213/godis/src/lib/logger"
|
||||
"github.com/HDT3213/godis/src/redis/client"
|
||||
"github.com/HDT3213/godis/src/redis/reply"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
self string
|
||||
|
||||
db *db.DB
|
||||
peerPicker *consistenthash.Map
|
||||
peers map[string]*client.Client
|
||||
}
|
||||
|
||||
const (
|
||||
replicas = 4
|
||||
)
|
||||
|
||||
func MakeCluster() *Cluster {
|
||||
cluster := &Cluster{
|
||||
self: config.Properties.Self,
|
||||
|
||||
db: db.MakeDB(),
|
||||
peerPicker: consistenthash.New(replicas, nil),
|
||||
peers: make(map[string]*client.Client),
|
||||
}
|
||||
if config.Properties.Peers != nil && len(config.Properties.Peers) > 0 {
|
||||
cluster.peerPicker.Add(config.Properties.Peers...)
|
||||
}
|
||||
return cluster
|
||||
}
|
||||
|
||||
// args contains all
|
||||
type CmdFunc func(cluster *Cluster, c redis.Client, args [][]byte) redis.Reply
|
||||
|
||||
func (cluster *Cluster) Close() {
|
||||
cluster.db.Close()
|
||||
}
|
||||
|
||||
var router = MakeRouter()
|
||||
|
||||
func (cluster *Cluster) Exec(c redis.Client, args [][]byte) (result redis.Reply) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.Warn(fmt.Sprintf("error occurs: %v\n%s", err, string(debug.Stack())))
|
||||
result = &reply.UnknownErrReply{}
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := strings.ToLower(string(args[0]))
|
||||
cmdFunc, ok := router[cmd]
|
||||
if !ok {
|
||||
return reply.MakeErrReply("ERR unknown command '" + cmd + "'")
|
||||
}
|
||||
result = cmdFunc(cluster, c, args)
|
||||
return
|
||||
}
|
||||
|
||||
// relay command to peer
|
||||
func (cluster *Cluster) Relay(key string, c redis.Client, args [][]byte) redis.Reply {
|
||||
peer := cluster.peerPicker.Get(key)
|
||||
if peer == cluster.self {
|
||||
// to self db
|
||||
return cluster.db.Exec(c, args)
|
||||
} else {
|
||||
peerClient, ok := cluster.peers[peer]
|
||||
// lazy init
|
||||
if !ok {
|
||||
var err error
|
||||
peerClient, err = client.MakeClient(peer)
|
||||
if err != nil {
|
||||
return reply.MakeErrReply(err.Error())
|
||||
}
|
||||
peerClient.Start()
|
||||
cluster.peers[peer] = peerClient
|
||||
}
|
||||
return peerClient.Send(args)
|
||||
}
|
||||
}
|
||||
|
||||
func (cluster *Cluster) AfterClientClose(c redis.Client) {
|
||||
|
||||
}
|
||||
102
src/cluster/router.go
Normal file
102
src/cluster/router.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package cluster
|
||||
|
||||
import "github.com/HDT3213/godis/src/interface/redis"
|
||||
|
||||
func defaultFunc(cluster *Cluster, c redis.Client, args [][]byte) redis.Reply {
|
||||
key := string(args[1])
|
||||
return cluster.Relay(key, c, args)
|
||||
}
|
||||
|
||||
func MakeRouter() map[string]CmdFunc {
|
||||
routerMap := make(map[string]CmdFunc)
|
||||
//routerMap["ping"] = defaultFunc
|
||||
|
||||
//routerMap["del"] = Del
|
||||
routerMap["expire"] = defaultFunc
|
||||
routerMap["expireat"] = defaultFunc
|
||||
routerMap["pexpire"] = defaultFunc
|
||||
routerMap["pexpireat"] = defaultFunc
|
||||
routerMap["ttl"] = defaultFunc
|
||||
routerMap["pttl"] = defaultFunc
|
||||
routerMap["persist"] = defaultFunc
|
||||
routerMap["exists"] = defaultFunc
|
||||
routerMap["type"] = defaultFunc
|
||||
//routerMap["rename"] = Rename
|
||||
//routerMap["renamenx"] = RenameNx
|
||||
|
||||
routerMap["set"] = defaultFunc
|
||||
routerMap["setnx"] = defaultFunc
|
||||
routerMap["setex"] = defaultFunc
|
||||
routerMap["psetex"] = defaultFunc
|
||||
//routerMap["mset"] = MSet
|
||||
//routerMap["mget"] = MGet
|
||||
//routerMap["msetnx"] = MSetNX
|
||||
routerMap["get"] = defaultFunc
|
||||
routerMap["getset"] = defaultFunc
|
||||
routerMap["incr"] = defaultFunc
|
||||
routerMap["incrby"] = defaultFunc
|
||||
routerMap["incrbyfloat"] = defaultFunc
|
||||
routerMap["decr"] = defaultFunc
|
||||
routerMap["decrby"] = defaultFunc
|
||||
|
||||
routerMap["lpush"] = defaultFunc
|
||||
routerMap["lpushx"] = defaultFunc
|
||||
routerMap["rpush"] = defaultFunc
|
||||
routerMap["rpushx"] = defaultFunc
|
||||
routerMap["lpop"] = defaultFunc
|
||||
routerMap["rpop"] = defaultFunc
|
||||
//routerMap["rpoplpush"] = RPopLPush
|
||||
routerMap["lrem"] = defaultFunc
|
||||
routerMap["llen"] = defaultFunc
|
||||
routerMap["lindex"] = defaultFunc
|
||||
routerMap["lset"] = defaultFunc
|
||||
routerMap["lrange"] = defaultFunc
|
||||
|
||||
routerMap["hset"] = defaultFunc
|
||||
routerMap["hsetnx"] = defaultFunc
|
||||
routerMap["hget"] = defaultFunc
|
||||
routerMap["hexists"] = defaultFunc
|
||||
routerMap["hdel"] = defaultFunc
|
||||
routerMap["hlen"] = defaultFunc
|
||||
routerMap["hmget"] = defaultFunc
|
||||
routerMap["hmset"] = defaultFunc
|
||||
routerMap["hkeys"] = defaultFunc
|
||||
routerMap["hvals"] = defaultFunc
|
||||
routerMap["hgetall"] = defaultFunc
|
||||
routerMap["hincrby"] = defaultFunc
|
||||
routerMap["hincrbyfloat"] = defaultFunc
|
||||
|
||||
routerMap["sadd"] = defaultFunc
|
||||
routerMap["sismember"] = defaultFunc
|
||||
routerMap["srem"] = defaultFunc
|
||||
routerMap["scard"] = defaultFunc
|
||||
routerMap["smembers"] = defaultFunc
|
||||
routerMap["sinter"] = defaultFunc
|
||||
routerMap["sinterstore"] = defaultFunc
|
||||
routerMap["sunion"] = defaultFunc
|
||||
routerMap["sunionstore"] = defaultFunc
|
||||
routerMap["sdiff"] = defaultFunc
|
||||
routerMap["sdiffstore"] = defaultFunc
|
||||
routerMap["srandmember"] = defaultFunc
|
||||
|
||||
routerMap["zadd"] = defaultFunc
|
||||
routerMap["zscore"] = defaultFunc
|
||||
routerMap["zincrby"] = defaultFunc
|
||||
routerMap["zrank"] = defaultFunc
|
||||
routerMap["zcount"] = defaultFunc
|
||||
routerMap["zrevrank"] = defaultFunc
|
||||
routerMap["zcard"] = defaultFunc
|
||||
routerMap["zrange"] = defaultFunc
|
||||
routerMap["zrevrange"] = defaultFunc
|
||||
routerMap["zrangebyscore"] = defaultFunc
|
||||
routerMap["zrevrangebyscore"] = defaultFunc
|
||||
routerMap["zrem"] = defaultFunc
|
||||
routerMap["zremrangebyscore"] = defaultFunc
|
||||
routerMap["zremrangebyrank"] = defaultFunc
|
||||
|
||||
//routerMap["flushdb"] = FlushDB
|
||||
//routerMap["flushall"] = FlushAll
|
||||
//routerMap["keys"] = Keys
|
||||
|
||||
return routerMap
|
||||
}
|
||||
1
src/cluster/string.go
Normal file
1
src/cluster/string.go
Normal file
@@ -0,0 +1 @@
|
||||
package cluster
|
||||
Reference in New Issue
Block a user