mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-05 08:46:56 +08:00

wip: raft does not care about migrating wip: optimize code wip: raft election wip wip: fix raft leader missing log entries wip fix a dead lock batch set slot route wip: raft persist wip refactor cluster suite remove relay rename relay2 refactor: allow customizing client factory test raft refactor re-balance avoid errors caused by inconsistent status on follower nodes during raft commits test raft election
167 lines
3.5 KiB
Go
167 lines
3.5 KiB
Go
package cluster
|
|
|
|
import (
|
|
"github.com/hdt3213/godis/interface/redis"
|
|
"strings"
|
|
)
|
|
|
|
// CmdLine is alias for [][]byte, represents a command line
|
|
type CmdLine = [][]byte
|
|
|
|
var router = make(map[string]CmdFunc)
|
|
|
|
func registerCmd(name string, cmd CmdFunc) {
|
|
name = strings.ToLower(name)
|
|
router[name] = cmd
|
|
}
|
|
|
|
func registerDefaultCmd(name string) {
|
|
registerCmd(name, defaultFunc)
|
|
}
|
|
|
|
// relay command to responsible peer, and return its protocol to client
|
|
func defaultFunc(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|
key := string(args[1])
|
|
slotId := getSlot(key)
|
|
peer := cluster.pickNode(slotId)
|
|
if peer.ID == cluster.self {
|
|
err := cluster.ensureKeyWithoutLock(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// to self db
|
|
//return cluster.db.Exec(c, cmdLine)
|
|
return cluster.db.Exec(c, args)
|
|
}
|
|
return cluster.relay(peer.ID, c, args)
|
|
}
|
|
|
|
func init() {
|
|
registerCmd("Ping", ping)
|
|
registerCmd("Prepare", execPrepare)
|
|
registerCmd("Commit", execCommit)
|
|
registerCmd("Rollback", execRollback)
|
|
registerCmd("Del", Del)
|
|
registerCmd("Rename", Rename)
|
|
registerCmd("RenameNx", RenameNx)
|
|
registerCmd("Copy", Copy)
|
|
registerCmd("MSet", MSet)
|
|
registerCmd("MGet", MGet)
|
|
registerCmd("MSetNx", MSetNX)
|
|
registerCmd("Publish", Publish)
|
|
registerCmd("Subscribe", Subscribe)
|
|
registerCmd("Unsubscribe", UnSubscribe)
|
|
registerCmd("FlushDB", FlushDB)
|
|
registerCmd("FlushAll", FlushAll)
|
|
registerCmd(relayMulti, execRelayedMulti)
|
|
registerCmd("Watch", execWatch)
|
|
registerCmd("FlushDB_", genPenetratingExecutor("FlushDB"))
|
|
registerCmd("Copy_", genPenetratingExecutor("Copy"))
|
|
registerCmd("Watch_", genPenetratingExecutor("Watch"))
|
|
registerCmd(relayPublish, genPenetratingExecutor("Publish"))
|
|
registerCmd("Del_", genPenetratingExecutor("Del"))
|
|
registerCmd("MSet_", genPenetratingExecutor("MSet"))
|
|
registerCmd("MSetNx_", genPenetratingExecutor("MSetNx"))
|
|
registerCmd("MGet_", genPenetratingExecutor("MGet"))
|
|
registerCmd("Rename_", genPenetratingExecutor("Rename"))
|
|
registerCmd("RenameNx_", genPenetratingExecutor("RenameNx"))
|
|
registerCmd("DumpKey_", genPenetratingExecutor("DumpKey"))
|
|
|
|
defaultCmds := []string{
|
|
"expire",
|
|
"expireAt",
|
|
"pExpire",
|
|
"pExpireAt",
|
|
"ttl",
|
|
"PTtl",
|
|
"persist",
|
|
"exists",
|
|
"type",
|
|
"set",
|
|
"setNx",
|
|
"setEx",
|
|
"pSetEx",
|
|
"get",
|
|
"getEx",
|
|
"getSet",
|
|
"getDel",
|
|
"incr",
|
|
"incrBy",
|
|
"incrByFloat",
|
|
"decr",
|
|
"decrBy",
|
|
"lPush",
|
|
"lPushX",
|
|
"rPush",
|
|
"rPushX",
|
|
"LPop",
|
|
"RPop",
|
|
"LRem",
|
|
"LLen",
|
|
"LIndex",
|
|
"LSet",
|
|
"LRange",
|
|
"HSet",
|
|
"HSetNx",
|
|
"HGet",
|
|
"HExists",
|
|
"HDel",
|
|
"HLen",
|
|
"HStrLen",
|
|
"HMGet",
|
|
"HMSet",
|
|
"HKeys",
|
|
"HVals",
|
|
"HGetAll",
|
|
"HIncrBy",
|
|
"HIncrByFloat",
|
|
"HRandField",
|
|
"SAdd",
|
|
"SIsMember",
|
|
"SRem",
|
|
"SPop",
|
|
"SCard",
|
|
"SMembers",
|
|
"SInter",
|
|
"SInterStore",
|
|
"SUnion",
|
|
"SUnionStore",
|
|
"SDiff",
|
|
"SDiffStore",
|
|
"SRandMember",
|
|
"ZAdd",
|
|
"ZScore",
|
|
"ZIncrBy",
|
|
"ZRank",
|
|
"ZCount",
|
|
"ZRevRank",
|
|
"ZCard",
|
|
"ZRange",
|
|
"ZRevRange",
|
|
"ZRangeByScore",
|
|
"ZRevRangeByScore",
|
|
"ZRem",
|
|
"ZRemRangeByScore",
|
|
"ZRemRangeByRank",
|
|
"GeoAdd",
|
|
"GeoPos",
|
|
"GeoDist",
|
|
"GeoHash",
|
|
"GeoRadius",
|
|
"GeoRadiusByMember",
|
|
"GetVer",
|
|
"DumpKey",
|
|
}
|
|
for _, name := range defaultCmds {
|
|
registerDefaultCmd(name)
|
|
}
|
|
|
|
}
|
|
|
|
// genPenetratingExecutor generates an executor that can reach directly to the database layer
|
|
func genPenetratingExecutor(realCmd string) CmdFunc {
|
|
return func(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|
return cluster.db.Exec(c, modifyCmd(cmdLine, realCmd))
|
|
}
|
|
}
|