Skip to content

Commit

Permalink
integrate redis-failover to support ha
Browse files Browse the repository at this point in the history
  • Loading branch information
siddontang committed Feb 12, 2015
1 parent 04d1406 commit dee32d5
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 1 deletion.
5 changes: 4 additions & 1 deletion Makefile
@@ -1,13 +1,16 @@
all: build

build: build-proxy build-config
build: build-proxy build-config build-ha

build-proxy:
godep go build -o bin/codis-proxy ./cmd/proxy

build-config:
godep go build -o bin/codis-config ./cmd/cconfig

build-ha:
godep go build -o bin/codis-ha ./cmd/ha

clean:
godep go clean -i ./...
@rm -rf bin
Expand Down
55 changes: 55 additions & 0 deletions cmd/ha/failover.go
@@ -0,0 +1,55 @@
package main

import (
"fmt"
log "github.com/ngaut/logging"
"github.com/ngaut/zkhelper"
"github.com/siddontang/xcodis/models"
"github.com/siddontang/xcodis/utils"
)

func Promote(oldMaster string, newMaster string) error {
conn, _ := zkhelper.ConnectToZk(*zkAddr)
defer conn.Close()

groups, err := models.ServerGroups(conn, *productName)
if err != nil {
return err
}

var groupId int
found := false
for _, group := range groups {
for _, server := range group.Servers {
if server.Addr == oldMaster {
groupId = group.Id
found = true
break
}
}
}

if !found {
return fmt.Errorf("can not find %s in any groups", oldMaster)
}

lock := utils.GetZkLock(conn, *productName)
lock.Lock(fmt.Sprintf("promote server %+v", newMaster))
defer func() {
err := lock.Unlock()
if err != nil {
log.Warning(err)
}
}()

group, err := models.GetGroup(conn, *productName, groupId)
if err != nil {
return err
}
err = group.Promote(conn, newMaster)
if err != nil {
return err
}

return nil
}
106 changes: 106 additions & 0 deletions cmd/ha/main.go
@@ -0,0 +1,106 @@
package main

import (
"flag"
"fmt"
"github.com/siddontang/redis-failover/failover"
"os"
"os/signal"
"strings"
"syscall"
)

var configFile = flag.String("config", "", "failover config file")
var addr = flag.String("addr", ":11000", "failover http listen addr")
var checkInterval = flag.Int("check_interval", 1000, "check master alive every n millisecond")
var maxDownTime = flag.Int("max_down_time", 3, "max down time for a master, after that, we will do failover")
var masters = flag.String("masters", "", "redis master need to be monitored, seperated by comma")
var mastersState = flag.String("masters_state", "", "new or existing for raft, if new, we will depracted old saved masters")
var raftDataDir = flag.String("raft_data_dir", "./var/store", "raft data store path")
var raftLogDir = flag.String("raft_log_dir", "./var/log", "raft log store path")
var raftAddr = flag.String("raft_addr", "", "raft listen addr, if empty, we will disable raft")
var raftCluster = flag.String("raft_cluster", "", "raft cluster,vseperated by comma")
var raftClusterState = flag.String("raft_cluster_state", "", "new or existing, if new, we will deprecate old saved cluster and use new")

var zkAddr = flag.String("zk", "", "zookeeper address")
var productName = flag.String("product", "test", "product name")

func main() {
flag.Parse()

var c *failover.Config
var err error
if len(*configFile) > 0 {
c, err = failover.NewConfigWithFile(*configFile)
if err != nil {
fmt.Printf("load failover config %s err %v", *configFile, err)
return
}
} else {
fmt.Printf("no config file, use default config")
c = new(failover.Config)
c.Addr = ":11000"
}

if *checkInterval > 0 {
c.CheckInterval = *checkInterval
}

if *maxDownTime > 0 {
c.MaxDownTime = *maxDownTime
}

if len(*raftAddr) > 0 {
c.Raft.Addr = *raftAddr
}

if len(*raftDataDir) > 0 {
c.Raft.DataDir = *raftDataDir
}

if len(*raftLogDir) > 0 {
c.Raft.LogDir = *raftLogDir
}

seps := strings.Split(*raftCluster, ",")
if len(seps) > 0 {
c.Raft.Cluster = seps
}

if len(*raftClusterState) > 0 {
c.Raft.ClusterState = *raftClusterState
}

seps = strings.Split(*masters, ",")
if len(seps) > 0 {
c.Masters = seps
}

if len(*mastersState) > 0 {
c.MastersState = *mastersState
}

app, err := failover.NewApp(c)
if err != nil {
fmt.Printf("new failover app error %v", err)
return
}

app.AddAfterFailoverHandler(Promote)

sc := make(chan os.Signal, 1)
signal.Notify(sc,
os.Kill,
os.Interrupt,
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT)

go func() {
<-sc
app.Close()
}()

app.Run()
}

0 comments on commit dee32d5

Please sign in to comment.