分布式数据库中间件 MyCat | 分库分表实践

摘要:
MyCat简介MyCat是一个强大的分布式数据库中间件和一个实现MySQL协议的服务器。前端人员可以将其视为数据库代理中间件,并使用MySQL客户端工具和命令行访问它;后端人员可以使用MySQL本地协议与多个MySQL服务器通信,也可以使用JDBC协议与大多数主流数据库服务器通信。

MyCat 简介

MyCat 是一个功能强大的分布式数据库中间件,是一个实现了 MySQL 协议的 Server,前端人员可以把它看做是一个数据库代理中间件,用 MySQL 客户端工具和命令行访问;而后端人员可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信。可以用作 读写分离分库分表(分片)容灾备份多租户应用开发大数据基础设施,使底层数据架构具备很强的适应性和灵活性。

MyCat 的智能优化模块可以使系统的数据访问瓶颈和热点一目了然,并且可以将这些统计分析数据自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码可以一行也不用变。

具体应用场景

  1. 读写分离:支持读写分离,主从切换,此配置最简单;
  2. 分库分表:对于超过 1000 万的表进行分片,最大支持 1000 亿的单表分片;
  3. 多租户应用:每个应用一个库,但应用程序只连接 MyCat,使程序不用改造本身,实现多租户化;
  4. 替代 Hbase:用于分析大数据;
  5. 报表系统:借助 MyCat 的分表能力,处理大规模报表的统计;
  6. 海量数据查询:比如 10 亿条频繁查询的记录需要在 3 秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时 MyCat 可能是最简单有效的选择。

本文主要实践核心功能 分库分表

分库分表原理剖析

指通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果。

根据切分规则的类型可以分为以下两种切分模式。

  • 垂直切分:最大特点是规则简单,适合各业务之间的的耦合度非常低、相互影响小、业务逻辑非常清晰的系统。在这种系统中,可以很容易 将不同业务模块所使用的的表切到不同的数据库中

  • 水平切分:相对来说复杂一些,因为要 将同一个表中的不同数据切分到不同的数据库中,后期的数据维护也更为复杂一些。

垂直切分

一个数据库由很多表构成,每个表对应着不同的业务,垂直切分就是按照业务将表进行分类,从而分布到不同的数据库上面,这样也就将压力分担到不同的数据库上,如图。

分布式数据库中间件 MyCat | 分库分表实践第1张

一个架构设计好的系统其总体功能通常是由多个功能模块所组成的,而每一个功能模块的数据对应到数据库中就是一个或多个表。而在架构设计中,各个功能模块相互之间的交互点越少和越统一,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好,这样的系统也就越容易实现垂直切分。

但是往往系统中有些表难以做到完全的独立,存在跨库 join 的情况,对于这类分库,可以共用一个数据源,业务之间通过接口来调用。

优点:规则明确、业务清晰、更易于整合和扩展、维护简单。

缺点:部分业务表无法 join,需要通过业务接口方式解决,提高系统复杂度;各业务存在单库性能瓶颈,不易于数据扩展和性能提高;事务处理复杂问题。

由于垂直切分是将表按照业务分类切分到不同的单库中,所有导致某些业务表过于庞大,存在单库读写与存储瓶颈,则需要水平切分来解决。

水平切分

水平切分不是将表按照业务分类,而是按照某个字段的某种规则分散到多个库中,每个表中包含一部分数据,如图。

分布式数据库中间件 MyCat | 分库分表实践第2张

拆分数据需要定义分片规则,拆分的第一原则是找到 拆分维度。比如:从会员的角度来分析,需要查询会员某天某月某个订单,那么就需要按照日期来拆分,不同的数据按照会员 ID 做分组。

优点:拆分规则抽象好;不存在单库数据瓶颈问题;提高系统稳定性和负载能力。

缺点:事务一致性难以解决;数据扩展和维护的难度极大;跨库 join 性能差。

附:多数据源管理方案

  • 第一种:客户端模式,在每个应用程序中配置管理自己需要的一个或多个数据源,直接访问各个数据库。
  • 第二种:通过中间代理层来统一管理所有的数据源。

搭建环境

均采用 Docker Compose 搭建服务

部署 3 台 MySQL 容器

分别创建 3 份 docker-compose.yml 文件

  • mysql-01

    version: '3.1'
    services:
      mysql-1:
        image: mysql
        container_name: mysql-01
        environment:
          MYSQL_ROOT_PASSWORD: 123456
        command:
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_general_ci
          --explicit_defaults_for_timestamp=true
          --lower_case_table_names=1
        ports:
          - 3306:3306
        volumes:
          - ./data:/var/lib/mysql
    
  • mysql-02

    version: '3.1'
    services:
      mysql-2:
        image: mysql
        container_name: mysql-02
        environment:
          MYSQL_ROOT_PASSWORD: 123456
        command:
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_general_ci
          --explicit_defaults_for_timestamp=true
          --lower_case_table_names=1
        ports:
          - 3307:3306
        volumes:
          - ./data:/var/lib/mysql
    
  • mysql-03

    version: '3.1'
    services:
      mysql-3:
        image: mysql
        container_name: mysql-03
        environment:
          MYSQL_ROOT_PASSWORD: 123456
        command:
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_general_ci
          --explicit_defaults_for_timestamp=true
          --lower_case_table_names=1
        ports:
          - 3308:3306
        volumes:
          - ./data:/var/lib/mysql
    

分别启动 3 台容器

$ docker-compose up -d

部署 MyCat 容器

  • 克隆项目

    $ git clone https://github.com/antoniopeng/docker.mycat.git
    
  • 构建镜像

    $ cd docker.mycat
    $ docker-compose build
    
  • 启动容器

    $ docker-compose up -d
    

配置数据库分片

此处以 水平切分 为例

配置用户名和密码

$ vi config/mycat/server.xml

找到第 90 行,参考配置如下:

<mycat:server xmlns:mycat="http://io.mycat/">
    
    <user name="root">
        
        <property name="password">123456</property>

        
        <property name="schemas">hellomycat</property>

        
        <property name="usingDecrypt">0</property>
    </user>
</mycat:server>

配置数据库节点

$ vi config/mycat/schema.xml

参考配置如下:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="hellomycat" checkSQLschema="true" sqlMaxLimit="100">
                
                <table />
        </schema>

        
        <dataNode name="dataNode1" dataHost="dataHost1" database="hellomycat_1" />
        <dataNode name="dataNode2" dataHost="dataHost2" database="hellomycat_2" />
        <dataNode name="dataNode3" dataHost="dataHost3" database="hellomycat_3" />

        
        <dataHost name="dataHost1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                
                <writeHost
                                host="192.168.127.130"
                                url="jdbc:mysql://192.168.127.130:3306?useSSL=false&amp;serverTimezone=UTC&amp;characterEncoding=utf8"
                                user="root" password="123456">
                        
                </writeHost>
        </dataHost>
        <dataHost name="dataHost2" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost
                                host="192.168.127.130"
                                url="jdbc:mysql://192.168.127.130:3307?useSSL=false&amp;serverTimezone=UTC&amp;characterEncoding=utf8"
                                user="root" password="123456">
                        
                </writeHost>
        </dataHost>
        <dataHost name="dataHost3" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="-1" slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost
                                host="192.168.127.130"
                                url="jdbc:mysql://192.168.127.130:3308?useSSL=false&amp;serverTimezone=UTC&amp;characterEncoding=utf8"
                                user="root" password="123456">
                        
                </writeHost>
        </dataHost>
        
</mycat:schema>

分片规则配置如下

$ vi config/mycat/rule.xml

第 32 行配置

<tableRule name="auto-sharding-long">
    <rule>
        
        <columns>id</columns>
        
        <algorithm>rang-long</algorithm>
    </rule>
</tableRule>

第 105 行配置

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    
    <property name="mapFile">autopartition-long.txt</property>
</function>

自定义数字范围分片规则

$ vi config/mycat/autopartition-long.txt

配置如下:

# range start-end ,data node index
# K=1000,M=10000.
# ID 0-5000000 保存在 dataNode1
0-500M=0
# ID 5000000-10000000 保存在 dataNode2
500M-1000M=1
# ID 10000000-15000000 保存在 dataNode3
1000M-1500M=2

验证是否成功

使用 MySQL 客户端工具连接 MyCat,默认端口号为 8066

  • 分别在 3 个数据库中创建表,只需要 ID 一个字段即可:

    create table sys_user (id int not null primary key);
    
  • 新增数据:

    insert into sys_user(id) values(2000000);
    insert into sys_user(id) values(7000000);
    insert into sys_user(id) values(1200000);
    

新增后如果 3 个数据库的表中都出现了一条数据,则说明分片成功。

免责声明:文章转载自《分布式数据库中间件 MyCat | 分库分表实践》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇LSPCI具体解释分析Windows 7下一个:该应用程序不能正常启动(0xc0150002)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL双主热备问题处理

1. Slave_IO_Running: No mysql> show slave statusG *************************** 1. row *************************** Slave_IO_State: Master_Host:...

mysql安装使用

  linux系统 mysql-5.7.14-linux.zip部署包支持在CentOS 6.x/7.x 服务器硬盘大小要求     a) /data/mysql_data  如果存在该独立分区,要求该分区 >10G b) 如果仅存在 /data 分区, 要求该分区 >10G c) 否则,要求根分区/ > 10G MySQL_INST...

如何优化mysql查询速度

1、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 2、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 3、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id fr...

MySQL访问控制

MySQL访问控制 【目的】 1、了解MySQL的访问控制原理 2、了解MySQL用户管理方法 3、掌握MySQL的基本权限操作语句 【知识点】 连接验证、修改权限、请求验证。 【原理】 数据库中通常包含重要的数据,这些数据的安全性和完整性需要通过访问控制来维护。MySQL的访问控制实际上就是为用户提供且仅提供他们所需的访问权。只有使用已有用户登录以...

Windows下Redmine 的安装步骤

本文介绍Windows下Redmine的安装步骤。1、给DOS添加ruby运行环境(下载并安装rubyinstaller-1.8.7-p249-rc2.exe)下载地址:http://rubyforge.org/frs/?group_id=167&release_id=42563(在下载页面中已经找不到1.8.7-p249了,应该下载rubyins...

ubuntu1704安装zabbix3.2

一、环境准备   部署zabbix要安装apache、mysql和php sudo apt-get install apache2 sudo apt-get install mysql-server #需要设密码 sudo apt-get install php7.0 php7.0-gd libapache2-mod-php7.0 php7.0-my...