Aliyun

aliyun-rds数据备份方案

本文主要是总结下在使用aliyun-rds数据备份方案过程中的心得。

高可用一直都是线上服务维护用户体验的关键之一。为了达到高可用,业界已经有了很多方案。最典型的就是“冗余备份+自动故障转移”。冗余备份是说,当一个节点服务不可用时,有其他服务能够代替其工作。除此之外,如果服务出现了必须人工介入解决的故障,也会影响系统的高可用特性。

本文着重介绍数据的高可用方案

数据库冗余 #

如果是单节点的数据库,还用的着说吗?要保证服务高可用,除了主-从数据库之外,还需要从备份数据库,当然不能保证说一定不会遇到所有的备份数据库,都挂掉的情况…。阿里云提供了RDS-高可用版本RDS-单机版,两者的区别见下图: 基础版和高可用 这就算最基本的冗余了,没有主从复制,没有读写分离。但是能保证主库在换掉的时候,还能使用备库提供服务。如果服务对于数据库性能和可用性有一定要求,那么可以在这个基础上升个级,见下图: 灾备方案

数据故障自动转移 #

已经有了冗余的数据库节点了,那么接下来要做的事情就是怎么感知数据库异常,并实现自动切换到备份实例中? 阿里云灾备方案的文档是这样描述的:

主实例和灾备实例均搭建主备高可用架构,当主实例所在区域发生突发性自然灾害等状况,主节点(Master)和备节点(Slave)均无法连接时,可将异地灾备实例切换为主实例,在应用端修改数据库链接地址后,即可快速恢复应用的业务访问。

对于主节点全部不可用的情况对应用服务是可见的,因此应用服务可以通过指定一些异常判断,在判定主节点不可用的时候,主动切换数据库连接地址来获取数据,提供服务。

// sql-detect.go

package main

import (
    "database/sql"
    "fmt"
    "sync"
    "time"

    _ "github.com/go-sql-driver/mysql"
    _ "github.com/mxk/go-sqlite"
)

var (
    mysqlAvailable bool    = true
    mutex                  = sync.Mutex{}
    db             *sql.DB = nil
)

func MysqlDetection(db *sql.DB, ticker *time.Ticker) {
    for {
        select {
        case <-ticker.C:
            if e := db.Ping(); e != nil {
                fmt.Println("got error", e)

                mutex.Lock()
                mysqlAvailable = false
                mutex.Unlock()

            } else {
                fmt.Println("status ok")
            }
        }
    }
}

func MysqlSwitch() {
    for {
        mutex.Lock()
        if !mysqlAvailable {
            fmt.Println("Switch Sqlite3")
            db, _ = sql.Open("sqlite3", "./foo.db")
        }
        mutex.Unlock()

        time.Sleep(time.Second * 4)
    }
}

func main() {
    c := make(chan bool)

    db, _ = sql.Open("mysql", "yeqiang:yeqiang@/test_yeqiang")
    ticker := time.NewTicker(time.Second * 2)

    go MysqlDetection(db, ticker)
    go MysqlSwitch()

    <-c
}

测试截图:

...

访问量 访客数