func (c *Canal) tryDump() error { if len(c.master.Name) > 0 && c.master.Position > 0 { // we will sync with binlog name and position log.Infof("skip dump, use last binlog replication pos (%s, %d)", c.master.Name, c.master.Position) return nil } if c.dumper == nil { log.Info("skip dump, no mysqldump") return nil } h := &dumpParseHandler{c: c} start := time.Now() log.Info("try dump MySQL and parse") if err := c.dumper.DumpAndParse(h); err != nil { return err } log.Infof("dump MySQL and parse OK, use %0.2f seconds, start binlog replication at (%s, %d)", time.Now().Sub(start).Seconds(), h.name, h.pos) c.master.Update(h.name, uint32(h.pos)) c.master.Save(true) return nil }
func (m *master) fullSync() error { log.Info("begin full sync") if err := m.conn.Send("fullsync"); err != nil { return err } m.state.Set(replSyncState) dumpPath := path.Join(m.app.cfg.DataDir, "master.dump") f, err := os.OpenFile(dumpPath, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer os.Remove(dumpPath) err = m.conn.ReceiveBulkTo(f) f.Close() if err != nil { log.Errorf("read dump data error %s", err.Error()) return err } if _, err = m.app.ldb.LoadDumpFile(dumpPath); err != nil { log.Errorf("load dump file error %s", err.Error()) return err } return nil }
func (t *electorTask) Run() error { t.z.wg.Add(1) defer t.z.wg.Done() log.Infof("begin leader %s, run", t.z.c.Addr) if err := t.z.getMasters(); err != nil { t.interrupted.Set(true) log.Errorf("get masters err %v", err) return err } t.z.noticeLeaderCh(true) for { select { case <-t.z.quit: log.Info("zk close, interrupt elector running task") t.z.noticeLeaderCh(false) t.interrupted.Set(true) return nil case <-t.stop: log.Info("stop elector running task") return nil case a := <-t.z.actionCh: if a.timeout.Get() { log.Warnf("wait action %s masters %v timeout, skip it", a.a.Cmd, a.a.Masters) } else { err := t.z.handleAction(a.a) a.ch <- err } } } return nil }
func (c *Canal) tryDump() error { if len(c.master.Name) > 0 { // we will sync with binlog name and position log.Infof("Skip dump, use last binlog replication pos (%s, %d)", c.master.Name, c.master.Position) return nil } if c.dumper == nil { log.Errorf("Skip dump, no dumper provided") return nil } h := &dumpParseHandler{c: c} start := time.Now() log.Info("Start dump") if err := c.dumper.DumpAndParse(h); err != nil { return errors.Trace(err) } log.Infof("Dump completed in %0.2f seconds", time.Now().Sub(start).Seconds()) c.master.Update(h.name, uint32(h.pos)) c.master.Save(true) return nil }
func (app *App) publishNewLog(l *rpl.Log) { if !app.cfg.Replication.Sync { //no sync replication, we will do async return } app.info.Replication.PubLogNum.Add(1) app.slock.Lock() slaveNum := len(app.slaves) total := (slaveNum + 1) / 2 if app.cfg.Replication.WaitMaxSlaveAcks > 0 { total = num.MinInt(total, app.cfg.Replication.WaitMaxSlaveAcks) } n := 0 logId := l.ID for _, s := range app.slaves { lastLogID := s.lastLogID.Get() if lastLogID == logId { //slave has already owned this log n++ } else if lastLogID > logId { log.Errorf("invalid slave %s, lastlogid %d > %d", s.slaveListeningAddr, lastLogID, logId) } } app.slock.Unlock() if n >= total { //at least total slaves have owned this log return } startTime := time.Now() done := make(chan struct{}, 1) go func() { n := 0 for i := 0; i < slaveNum; i++ { id := <-app.slaveSyncAck if id < logId { log.Infof("some slave may close with last logid %d < %d", id, logId) } else { n++ if n >= total { break } } } done <- struct{}{} }() select { case <-done: case <-time.After(time.Duration(app.cfg.Replication.WaitSyncTime) * time.Millisecond): log.Info("replication wait timeout") } stopTime := time.Now() app.info.Replication.PubLogAckNum.Add(1) app.info.Replication.PubLogTotalAckTime.Add(stopTime.Sub(startTime)) }