-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathfailover.go
67 lines (57 loc) · 1.75 KB
/
failover.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package failover
import (
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/pingcap/errors"
)
// Failover will do below things after the master down
// 1. Elect a slave which has the most up-to-date data with old master
// 2. Promote the slave to new master
// 3. Change other slaves to the new master
//
// Limitation:
// 1, All slaves must have the same master before, Failover will check using master server id or uuid
// 2, If the failover error, the whole topology may be wrong, we must handle this error manually
// 3, Slaves must have same replication mode, all use GTID or not
func Failover(flavor string, slaves []*Server) ([]*Server, error) {
var h Handler
var err error
switch flavor {
case mysql.MySQLFlavor:
h = new(MysqlGTIDHandler)
case mysql.MariaDBFlavor:
return nil, errors.Errorf("MariaDB failover is not supported now")
default:
return nil, errors.Errorf("invalid flavor %s", flavor)
}
// First check slaves use gtid or not
if err := h.CheckGTIDMode(slaves); err != nil {
return nil, errors.Trace(err)
}
// Stop all slave IO_THREAD and wait the relay log done
for _, slave := range slaves {
if err = h.WaitRelayLogDone(slave); err != nil {
return nil, errors.Trace(err)
}
}
var bestSlave *Server
// Find best slave which has the most up-to-data data
if bestSlaves, err := h.FindBestSlaves(slaves); err != nil {
return nil, errors.Trace(err)
} else {
bestSlave = bestSlaves[0]
}
// Promote the best slave to master
if err = h.Promote(bestSlave); err != nil {
return nil, errors.Trace(err)
}
// Change master
for i := 0; i < len(slaves); i++ {
if bestSlave == slaves[i] {
continue
}
if err = h.ChangeMasterTo(slaves[i], bestSlave); err != nil {
return nil, errors.Trace(err)
}
}
return slaves, nil
}