文章目录
- 前言
- 一、MySQL的集群架构
- 二、MySQL主从同步实践
- 1.创建主节点实例
- 2.创建从节点实例
- 3.修改配置
- 4.开始同步
- 4.测试主从同步效果
- 5.小结
- 三、MySQL分库分表
- 1.配置sharding-proxy
- 2.测试sharding-proxy
- 3.小结
前言
本篇是谷粒商城集群部署篇,搭建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
分库分表代理的配置信息:
配置文件中有几个关键的点:
- 需要设置
物理数据库
和逻辑数据库
的映射关系。即请求先到达设置的逻辑数据库,再根据规则转发到绑定的物理数据库上。 - 分库分表后,主键不能使用自增,因为这样会存在主键重复的问题。需要采用分布式的唯一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集群