raft cluster

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
This commit is contained in:
finley
2023-01-02 21:27:06 +08:00
parent df672d4c92
commit bf7f628810
54 changed files with 3122 additions and 703 deletions

View File

@@ -136,23 +136,23 @@ func (client *Client) Send(args [][]byte) redis.Reply {
if atomic.LoadInt32(&client.status) != running {
return protocol.MakeErrReply("client closed")
}
request := &request{
req := &request{
args: args,
heartbeat: false,
waiting: &wait.Wait{},
}
request.waiting.Add(1)
req.waiting.Add(1)
client.working.Add(1)
defer client.working.Done()
client.pendingReqs <- request
timeout := request.waiting.WaitWithTimeout(maxWait)
client.pendingReqs <- req
timeout := req.waiting.WaitWithTimeout(maxWait)
if timeout {
return protocol.MakeErrReply("server time out")
}
if request.err != nil {
return protocol.MakeErrReply("request failed")
if req.err != nil {
return protocol.MakeErrReply("request failed " + req.err.Error())
}
return request.reply
return req.reply
}
func (client *Client) doHeartbeat() {

View File

@@ -50,8 +50,8 @@ var connPool = sync.Pool{
}
// RemoteAddr returns the remote network address
func (c *Connection) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
func (c *Connection) RemoteAddr() string {
return c.conn.RemoteAddr().String()
}
// Close disconnect with the client

View File

@@ -104,3 +104,7 @@ func (c *FakeConn) Close() error {
c.notify()
return nil
}
func (c *FakeConn) RemoteAddr() string {
return ""
}

View File

@@ -1,5 +1,10 @@
package protocol
import (
"bytes"
"github.com/hdt3213/godis/interface/redis"
)
// PongReply is +PONG
type PongReply struct{}
@@ -57,6 +62,10 @@ func MakeEmptyMultiBulkReply() *EmptyMultiBulkReply {
return &EmptyMultiBulkReply{}
}
func IsEmptyMultiBulkReply(reply redis.Reply) bool {
return bytes.Equal(reply.ToBytes(), emptyMultiBulkBytes)
}
// NoReply respond nothing, for commands like subscribe
type NoReply struct{}

View File

@@ -35,8 +35,7 @@ type Handler struct {
// MakeHandler creates a Handler instance
func MakeHandler() *Handler {
var db database.DB
if config.Properties.Self != "" &&
len(config.Properties.Peers) > 0 {
if config.Properties.ClusterEnable {
db = cluster.MakeCluster()
} else {
db = database2.NewStandaloneServer()
@@ -71,7 +70,7 @@ func (h *Handler) Handle(ctx context.Context, conn net.Conn) {
strings.Contains(payload.Err.Error(), "use of closed network connection") {
// connection closed
h.closeClient(client)
logger.Info("connection closed: " + client.RemoteAddr().String())
logger.Info("connection closed: " + client.RemoteAddr())
return
}
// protocol err
@@ -79,7 +78,7 @@ func (h *Handler) Handle(ctx context.Context, conn net.Conn) {
_, err := client.Write(errReply.ToBytes())
if err != nil {
h.closeClient(client)
logger.Info("connection closed: " + client.RemoteAddr().String())
logger.Info("connection closed: " + client.RemoteAddr())
return
}
continue