一点一滴成长

导航

MySQL Cluster与Replication

1、综述 

  MySql架构可以分为两种形式,一个是MySQL Cluster,一个是MySQL Replication,Cluster即集群模式,Replication即主从复制(读写分离)模式。

  MySQL Cluster基于NDB存储引擎,其优点是高可用(即节点出现故障时自动切换到备用节点)和高可伸缩性(可以添加或删除节点以提高系统扩展性),并且实时性能高(数据存储在内存中,并可通过多个节点来分布查询),缺点是配置复杂,而且数据需要存储在内存中,需要许可费用(MySQL Cluster是商业产品),所以其成本较高。

  MySQL Replication基于InnoDB存储引擎,它是一种简单的主服务器和多个从服务器的架构,可以在主服务器上写入数据,并在从服务器上进行读取操作,通过添加更多的从服务器来提高系统的扩展性。Replication在故障切换方面比较弱,并不能提供完全的自动故障转移机制,如果主服务器负载过大,可能会影响读写性能,而且Slaves的数据同步的延迟也可能比较大。

2、主从复制

  MySQL主从复制原理:当Master主库进行写入命令时,会按将其写入到binlog中,然后由Binlog Dump 线程将变化内容推送给所有slave节点,slave节点收到推送后会根据内容对数据库做对应的修改(为了减小延迟,从节点会通过 I/O 线程将主服务器的二进制日志文件中的写操作复制到一个叫 Relay Log 的中继日志文件,然后通过另一个 SQL 线程将 Relay Log 中继日志文件中的写操作依次在本地执行)。当salve从库连接到master主库后会向其发送当前收到的修改内容的偏移量,master主库收到后会对比自己的binlog修改偏移量,如果不同的话会向salve从库进行主从复制。默认是基于语句的复制,即把命令在从服务器上执行一遍,无法精确执行语句复制的时候会自动选择基于行的复制,即把改变的内容复制过去。

  可以通过mysql配置文件来对MySQL服务进行Master和Slave配置,然后在代码中只对master进行写入数据,slave负责读取数据。在SpringBoot项目中实现读写分离模式的话可以参考这两篇文章:MySQL主从复制读写分离,看这篇就够了SpringBoot 项目优雅实现读写分离

3、链式复制和双向复制

  除了一个Master多个Slave的常规复制架构外,还有链式复制和双向复制,因为Slave可以同时作为Master,从而形成链式复制和双向复制。

  当读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑住读的压力,这时候写入的话Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,容易造成复制延时,这个时候就可以使用链式复制。如下所示,先通过少数几台Slave从Master进行复制(第一级Slave集群),然后其他的Slave再从第一级Slave集群来进行复制(第二级Slave集群)。这样可以解决Master端因为附属Slave太多而成为瓶颈的风险。

  

  在Master端需要进行一些特别的维护操作的时候,可能需要停MySQL的服务,为了尽可能减少应用系统写服务的停机时间,可以使用双向复制架构:两个MySQL服务互相将对方作为自己的Master,即将自己配置为对方的Slave,这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。因为任何一端都记录了自己当前复制到对方的什么位置了,当服务起来之后,就会自动开始从之前的位置开始复制,而不需要人为去进行任何干预,大大节省了维护成本。双向复制架构和一些第三方的HA(High Available高可用)管理软件结合,可以在我们当前正在使用的Master出现异常无法提供服务之后,非常迅速的自动切换另外一端来提供相应的服务,并且完全不需要人工干预。官方文档中并不提倡使用双向复制架构,因为容易产生冲突。

  

4、高可用方案

  

  MySQL的整体架构可以如上所示,对于常规主从复制模式的话,可以使用drbd来保证两个master库(一个主Master,一个备份Master)的数据一致性,利用heartbeat来完成其中一台mater发生故障后的自动切换,如下所示。如果是双向复制模式,各自作为对方的从机接受对方发来的数据,可以自动做到数据的同步备份,然后可以使用MMM(MySQL Master-Master Replication Manager)来保证其中一台服务器故障,自动切换到另外的一个master上。其它的HA组件还有mha、orchestrator、replication-manager等,也可以使用server内置插件如MGR、PXC、MariaDB Galera Cluster等。

5、MyCat

  也可以使用MyCat来实现MySQL集群,MyCat相当于是一个分布式数据库系统,其实现了MySQL协议,可以将其看做一个数据库代理,其核心功能是分表分库,即将一个大表分割成N个小表,存储在后端的一个或多个MySQL服务中。MyCat后端不仅可以用MySQL原生协议与MySQL服务通信,也可以使用JDBC协议与其它主流数据库服务通信,所以其后端也可以支持SQL Server、Oracle、DB2等。而在前端用户看来,无论使用哪种存储服务,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据操作。  

6、MySQL++

  C++中可以使用MySQL++这个库来简化MySQL操作,它可以将查询结果转存到STL容器中——顺序的或关联的,同时支持连接池。使用示例如下:

mysqlpp::Connection conn(false);
    conn.connect(DATEBASE_NAME, DATEBASE_IP, DATEBASE_USERNAME, DATEBASE_PWD);

    mysqlpp::Query query = conn.query();
    query << "select * from cc;";

    mysqlpp::StoreQueryResult ares = query.store();
    for (size_t i = 0; i < ares.num_rows(); i++)
    {
        cout << "id: " << ares[i]["id"] << ","
          << "Name: " << ares[i]["name"] << ","
          << "Status: " << ares[i]["status"] << endl;
    }
    mysqlpp::Query query = conn.query("SELECT * FROM student");
    if (mysqlpp::StoreQueryResult res = query.store()) {
        mysqlpp::StoreQueryResult::const_iterator it;
        for (it = res.begin(); it != res.end(); ++it)
        {
            mysqlpp::Row row = *it;
            cout << row[0] << ','
                    << row[1] << ','
                    << row[2] << endl;
        }
    }
    vector<mysqlpp::Row> v;
    query << "SELECT * FROM stock";
    query.storein(v);
    for (vector<mysqlpp::Row>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << "Price: " << it->at("price") << endl;
    }
    vector<Stock> v;
    query << "SELECT * FROM stock";
    query.storein(v);
    for (vector<Stock>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << "Price: " << it->price << endl;
    }

 使用连接池的话,可以从mysqlpp::ConnectionPool继承出一个连接池类,然后从这个连接池对象中获得一个连接来直接使用,具体可以参考MySQL++ Documentation中User Manual中的Using MySQL++ in a Multithreaded Program部分。

  关于MySQL++的安装可以参考Linux环境下Mysql++安装及操作深入详解C++ 操作mySQLmysql++安装、使用详解

posted on 2024-01-23 17:22  整鬼专家  阅读(20)  评论(0编辑  收藏  举报