前言

  本篇是谷粒商城集群部署篇,搭建MySQL集群以及分库分表实践的个人笔记,采用主从架构,以及sharding-proxy。


一、MySQL的集群架构

  MySQL的集群架构,简单来说可以分为主从架构,主主架构,主备架构。

  • 主从架构是最常见的一种,通常是集群中有一个主节点,多个从节点,主节点负责数据的写入,从节点负责读取。这样做可以实现读写分离。主从之间的数据也需要同步。
  • 主主架构则是两个 MySQL 服务器相互作为主数据库,既可以接收写请求,也可以向对方同步数据。但是两台主机都有写入操作时,可能会导致数据不一致,需要额外的冲突解决机制。
  • 主备架构是,备节点是主节点的副本,会复制主节点的数据,主节点宕机后,立刻切换备用节点作为主节点。

  关于各类中间件集群如何保证高可用性,是面试中几乎必问的问题,以及MySQL如何进行主从复制?保证主从数据的一致性?这些衍生问题都会放在 MySQL的面试题总结中。

二、MySQL主从同步实践

1.创建主节点实例

docker run -p 3307:3306 --name mysql-master \
-v /mydata/mysql/master/log:/var/log/mysql \
-v /mydata/mysql/master/data:/var/lib/mysql \
-v /mydata/mysql/master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

2.创建从节点实例

docker run -p 3317:3306 --name mysql-slaver-01 \
-v /mydata/mysql/slaver/log:/var/log/mysql \
-v /mydata/mysql/slaver/data:/var/lib/mysql \
-v /mydata/mysql/slaver/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

在这里插入图片描述

3.修改配置

  首先进入主节点的conf目录,创建my.cnf文件:

vi /mydata/mysql/master/conf/my.cnf

在这里插入图片描述  编辑内容:

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqld]
init_connect='SET collation_connection = utf8mb4_unicode_ci; SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

server_id=1
log-bin=mysql-bin
read-only=0

# 需要同步的库
binlog-do-db=gulimall_ums
binlog-do-db=gulimall_pms
binlog-do-db=gulimall_oms
binlog-do-db=gulimall_sms
binlog-do-db=gulimall_wms
binlog-do-db=gulimall_admin

# 忽略同步的库(系统自带)
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

  从节点同理,配置文件如下,区别主节点在于server_id,以及read-only=1,从节点是只读的。

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqld]
init_connect='SET collation_connection = utf8mb4_unicode_ci; SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

server_id=2
log-bin=mysql-bin
read-only=1

binlog-do-db=gulimall_ums
binlog-do-db=gulimall_pms
binlog-do-db=gulimall_oms
binlog-do-db=gulimall_sms
binlog-do-db=gulimall_wms
binlog-do-db=gulimall_admin

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

  然后重启主从节点:

docker restart mysql-master mysql-slaver-01

在这里插入图片描述

4.开始同步

  使用如下命令进入主节点mysql实例,并输入密码:

docker exec -it mysql-master bash
mysql -uroot -p

在这里插入图片描述
  授权root用户可以远程访问,方便使用可视化工具连接

grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;

  创建一个从节点用于同步的用户

GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by '123456';

  查看主节点状态

show master status

在这里插入图片描述  然后同样的方式进入从节点,同样授权远程访问,然后执行以下命令设置主节点链接:

CHANGE MASTER TO 
    MASTER_HOST = '你自己的虚拟机地址',
    MASTER_USER = 'backup',
    MASTER_PASSWORD = '123456',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 0,
    MASTER_PORT = 3307;

  启动主从同步:

start slave;

  查看主从同步的状态,如图代表成功:

show slave status\G;

在这里插入图片描述

4.测试主从同步效果

  在主节点中创建一个数据库(注意,创建的数据库必须是在主库my.cnf中配置的同步数据库),这里创建的是gulimall_oms:
在这里插入图片描述  刷新从节点,gulimall_oms被同步创建。
在这里插入图片描述  向主节点的表中添加一条数据:
在这里插入图片描述  刷新从节点,数据被同步更新:
在这里插入图片描述

5.小结

  在主从节点的配置中,必须指定有哪些数据库是需要同步的。后续如果有新的数据库需要同步,需要修改配置文件。在主从同步之前,主节点需要创建一个从节点用于同步的用户,从节点需要使用该用户设置主节点链接

三、MySQL分库分表

1.配置sharding-proxy

  MySQL的分库分表,使用sharding-proxy,官网上下载后,需要将MySQL的jar包复制到lib目录下:
在这里插入图片描述  修改server.yaml配置信息:
在这里插入图片描述

authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding 
      authorizedSchemas: sharding_db
#
props:
#  max.connections.size.per.query: 1
#  acceptor.size: 16  # The default value is available processors count * 2.
  executor.size: 16  # Infinite by default.
#  proxy.frontend.flush.threshold: 128  # The default value is 128.
#    # LOCAL: Proxy will run with LOCAL transaction.
#    # XA: Proxy will run with XA transaction.
#    # BASE: Proxy will run with B.A.S.E transaction.
#  proxy.transaction.type: LOCAL
#  proxy.opentracing.enabled: false
#  query.with.cipher.column: true
  sql.show: false

  再修改config-sharding.yaml分库分表代理的配置信息:
在这里插入图片描述
  配置文件中有几个关键的点:

  1. 需要设置物理数据库和逻辑数据库的映射关系。即请求先到达设置的逻辑数据库,再根据规则转发到绑定的物理数据库上。
  2. 分库分表后,主键不能使用自增,因为这样会存在主键重复的问题。需要采用分布式的唯一ID。
schemaName: sharding_db #将demo_ds_0和demo_ds_1 数据库映射到 sharding_db 上	sharding_db 在 ShardingSphere 中代表一个逻辑数据库,它将应用程序的数据库访问请求转发到多个物理数据库(或数据源)上
#
dataSources:
	# 定义第一个物理数据库
  ds_0:
    url: jdbc:mysql://192.168.101.128:3307/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  # 定义第二个物理数据库
  ds_1:
    url: jdbc:mysql://192.168.101.128:3307/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
# 指定分库分表规则
shardingRule:
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..1} #ds_0 和 ds_1 数据源下分为两个表:t_order_0 和 t_order_1
      tableStrategy:
        inline:
          shardingColumn: order_id # 用来做分片的列
          algorithmExpression: t_order_${order_id % 2} # 分片算法表达式,根据 order_id 对 2 取余来选择 t_order_0 或 t_order_1
      keyGenerator:
        type: SNOWFLAKE #指定主键规则为雪花算法
        column: order_id #雪花算法生成的主键将存储在 order_id 列
    t_order_item:
      actualDataNodes: ds_${0..1}.t_order_item_${0..1} #ds_0 和 ds_1 数据源下分为两个表:t_order_item_0 和 t_order_item_1
      tableStrategy:
        inline:
          shardingColumn: order_id # 用来做分片的列
          algorithmExpression: t_order_item_${order_id % 2}  # 分片算法表达式,根据 order_id 对 2 取余来选择 t_order_item_0 或t_order_item_1
      keyGenerator:
        type: SNOWFLAKE #指定主键规则为雪花算法
        column: order_item_id #雪花算法生成的主键将存储在 order_id 列
  bindingTables:
    - t_order,t_order_item #这两个表在分片时会使用相同的分片策略
  defaultDatabaseStrategy:
    inline:
      shardingColumn: user_id  # 用来做数据库分片的列
      algorithmExpression: ds_${user_id % 2}  # 分片算法表达式,根据 user_id 对 2 取余来选择 ds_0 或 ds_1 数据源
  defaultTableStrategy:
    none:

  依据上述配置文件的逻辑,首先请求先到达设置的逻辑数据库,再根据规则转发到绑定的物理数据库上,根据 user_id 对 2 取余来选择 ds_0 或 ds_1 数据库。在ds_0 或 ds_1 数据库中,又会根据order_id 对 2 取余来选择 走哪张表。

  最后修改config-master_slave.yaml读写分离的配置文件,这里的demo_ds_0,demo_ds_1都在同一个主节点,从节点的连接上。

schemaName: sharding_db_1
#
dataSources: 
  master_0_ds: #数据库1的主节点
    url: jdbc:mysql://192.168.101.128:3307/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  slave_ds_0: #数据库1的从节点
    url: jdbc:mysql://192.168.101.128:3317/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
masterSlaveRule:
 name: ms_ds
 masterDataSourceName: master_0_ds
 slaveDataSourceNames:
   - slave_ds_0

  需要再复制一份config-master_slave.yaml:

schemaName: sharding_db_2
#
dataSources:
  master_1_ds: #数据库2的主节点
    url: jdbc:mysql://192.168.101.128:3307/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  slave_ds_1: #数据库2的从节点
    url: jdbc:mysql://192.168.101.128:3317/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
masterSlaveRule:
  name: ms_ds_1
  masterDataSourceName: master_1_ds
  slaveDataSourceNames:
    - slave_ds_1
  #  - slave_ds_1
  #  - slave_ds_1

  如果lib目录下的jar包后缀.jar不全,需要手动替换:
在这里插入图片描述  同时因为需要加入demo_ds_0和demo_ds_1两个库,主节点和从节点需要修改my.cnf:

docker stop mysql-slaver-01 mysql-master

在这里插入图片描述  重启主从节点:

docker start mysql-slaver-01 mysql-master

  然后去主节点中创建两个数据库(从节点会自动同步):

在这里插入图片描述  双击bin目录的start.bat启动(注意,路径下不能有中文,我重新换了位置):
在这里插入图片描述  如下图就是启动成功:
在这里插入图片描述

2.测试sharding-proxy

  在启动时指定一个端口号:
在这里插入图片描述  可以用远程连接工具连接sharding-proxy:
在这里插入图片描述  三个虚拟库对应的就是在config-master_slave.yaml配置文件里的,下面在sharding_db中创建测试表:

在这里插入图片描述

CREATE TABLE `t_order` (
`order_id` bigint(20) NOT NULL, `user_id` int(11) NOT NULL, `status` varchar(50) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `t_order_item` (
`order_item_id` bigint(20) NOT NULL, `order_id` bigint(20) NOT NULL, `user_id` int(11) NOT NULL, `content` varchar(255) COLLATE utf8_bin DEFAULT NULL, `status` varchar(50) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`order_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

  在主节点和从节点上已经进行了分表(在demo_ds_1 和 demo_ds_0 中都一样)
在这里插入图片描述在这里插入图片描述  当进行数据操作时,请求实际上是通过sharding_db去根据规则路由到不同的数据库,表的,向sharding_db的t_order插入三条数据:

insert INTO t_order(user_id,status) VALUES(1,1);
insert INTO t_order(user_id,status) VALUES(2,1);
insert INTO t_order(user_id,status) VALUES(3,1);

在这里插入图片描述  但是在实际的物理数据库已经根据规则进行了分库分表,userId % 2 = 0的被分在了demo_ds_0中,userId % 2 != 0的被分在了demo_ds_1中,根据order_id也决定了数据落入demo_ds_0或是demo_ds_1库的哪张表里。
在这里插入图片描述在这里插入图片描述

3.小结

  使用sharding-proxy进行分库分表,首先需要修改配置文件,包括数据库的主从信息,连接信息,以及分库分表的规则。在开发中,只需要连接sharding-proxy的虚拟数据库,在创建表时,就会对物理数据库进行分表。操作其中的表时,sharding-proxy根据配置好的规则,将数据实际路由到真正的业务表中。


下一篇:谷粒商城のRedis集群

更多推荐