第105讲:Mycat垂直分表实战:从规划到解决问题的完整指南

news2024/12/21 4:41:31

文章目录

    • 1.垂直分表的背景
    • 2.垂直分表案例实战
      • 2.1.垂直分表规划
      • 2.2.配置Mycat实现垂直分表
      • 2.3.重启Mycat
      • 2.4.在Mycat命令行中导入数据结构
      • 2.5.查看由Mycat分表后每个分片上存储的表
      • 2.6.Mycat垂直分表后可能遇到的问题
      • 2.7.垂直分表完成

1.垂直分表的背景

我们的商城系统数据库,目前是单点数据库,随着业务量越来越大,每日产生的数据量越来越多,单台数据库的存储能力和计算能力是有限的,为了保证用户的体验度和满意度,在数据库性能到达瓶颈之前,我们先对数据进行性能优化,目前的优化方案是对商城库进行垂直分表,扩展数据库节点,将不同业务的表存储在多个数据库节点中,提高数据库的性能。

垂直分库指的是将一个库中的多个表,拆分到多个数据库实例中,也就是拆分到了多台不同的数据库服务器上,缓解了单台数据库所承担的压力。

image-20220713204639355

2.垂直分表案例实战

2.1.垂直分表规划

为了保证数据库的高可用性和读写分离,我们在前面准备了2套双主双从的集群,我们按照双主双从集群进行划分,每一套双主双从充当一个数据节点也就是分片,将商品库的这些表分别存放在不同的节点分片中,从而达到分表的目的。

如下图所示,商品库的所有表的划分情况如下:

  • 将tb_goods_base、tb_goods_brand、tb_goods_cat、tb_goods_desc、tb_goods_item、tb_user、tb_user_address这7张表划分到分片1这个双主双从集群中。
  • 将tb_order_item、tb_order_master、tb_order_pay_log、tb_areas_city、tb_areas_region、tb_areas_provinces这6张表划分到分片2这个双主双从集群中。

image-20220713204300489

利用Mycat实现垂直分表的思路:

  • 首先声明一个schema,定义逻辑库,逻辑库就是这个商品库。
  • 然后定义逻辑表table,根据不同的表划分到不同的数据节点dataNode上。
  • 然后定义dataNode关联数据库节点中真实的数据库。
  • 最后定义dataHost也就是分片,一共定义2组分片,分别指向各自的双主双从复制集群。

此架构实现后,我们的商品库就从单点架构升级达到了双主双从高可用+读写分离的架构,并且也从逻辑上进行了分库分表操作,提供数据库性能。

2.2.配置Mycat实现垂直分表

1)在Schema配置文件中配置垂直分表

关于配置参数有几点需要说明一下:

  • 如果在<schema>标签中指定了dataNode数据节点,那么该逻辑库下所有的表都会被存储到指定数据节点的数据库实例上。
  • 如果单独在<table>逻辑表标签中定义了dataNode数据节点,那么该数据节点的优先级将大于schema中的数据节点,会根据逻辑表标签中的定义的dataNode,将该表存放在指定的数据库实例中。
  • 由于我们的分片一共有两个,因此我们要定义两个dataNode数据节点,一个数据节点相当于是一个分片,然后将指定的表、库按照需求划分到对应的分片上。
  • 定义好分片后,就需要去定义dataHost数据主机了,一个分片对应一个dataHost,因此我们需要定义两组dataHost,第一套双主双从集群分片主机为mysqlcluster-1,第二套双主双从集群分片主机为mysqlcluster-2。
  • 然后在dataHost中去指定数据存储的具体数据库实例,也就是我们的双主双从集群,双主双从集群也是两套主从复制集群,我们配置成两组<writeHost>,双主双从集群只有一个主库承担写操作,另一个主库充当备用主库,当主库故障后,备用主库直接切换成主库,形成高可用集群,双从全部承担读操作。

Schema配置文件的逻辑调用关系如下:

<schema>中包含<table>,定义要对那些库和表进行操作,逻辑库和逻辑表都会关联数据节点<dataNode>,在数据节点中关联数据主机<dataHost>和真实数据库名称,在<dataHost>中定义数据库实例信息。

一个逻辑库或者逻辑表的分库分表操作,是根据关联数据节点确定要将库、表分在哪个数据库节点上,然后关联的数据节点找到具体的数据主机,最后库、表就分在了关联的数据主机上。

[root@mysql-1 ~]# vim /data/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
<mycat:schema xmlns:mycat="http://io.mycat/">
		 <!--定义逻辑库 库名叫做db_shopping 该逻辑库关联dn1这个数据节点--> 	
        <schema name="db_shopping" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
			<!--定义逻辑表 将部分表划分到dn1这个分片-->
			<table name="tb_goods_base" dataNode="dn1" primaryKey="id"/>
			<table name="tb_goods_brand" dataNode="dn1"/>
			<table name="tb_goods_cat" dataNode="dn1"/>
			<table name="tb_goods_desc" dataNode="dn1"/>
			<table name="tb_goods_item" dataNode="dn1"/>
			<table name="tb_user" dataNode="dn1"/>
             <table name="tb_user_address" dataNode="dn1"/>

			<!--定义逻辑表 将部分表划分到dn2这个分片-->
			<table name="tb_order_item" dataNode="dn2"/>
			<table name="tb_order_master" dataNode="dn2"/>
			<table name="tb_order_pay_log" dataNode="dn2"/>
			<table name="tb_areas_city" dataNode="dn2"/>
			<table name="tb_areas_region" dataNode="dn2"/>
			<table name="tb_areas_provinces" dataNode="dn2"/>
		</schema>  

		<!--定义数据节点 也就是分片 一个分片会关联一个数据主机组 然后对应真实的数据库名称-->
        <dataNode name="dn1" dataHost="mysqlcluster-1" database= "db_shopping" />          
        <dataNode name="dn2" dataHost="mysqlcluster-2" database= "db_shopping" />          

		<!--定义数据主机 在这个标签下定义具体的读写操作路由的数据库实例地址 schema、table划分如何指定的是该数据主机关联的数据节点 那么对应的库、表都会被存储在数据主机定义的数据库实例中-->
        <dataHost name="mysqlcluster-1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                <heartbeat>select user()</heartbeat>  
				<!--定义写操作路由的数据库实例-->
                <writeHost host="c1-1-master3306" url="192.168.20.11:3306" user="root" password="123456">
						<!--定义读操作路由的数据库实例-->
                        <readHost host="c1-1-slave3308" url="192.168.20.11:3308" user="root" password="123456" />
                </writeHost> 
				<!--备用的主库 也是提供写操作的数据库,当主库c1-1-master3306故障后 备用库开始提供写操作-->
                <writeHost host="c1-2-master3306" url="192.168.20.12:3306" user="root" password="123456">
						<!--备用主库的从库 从始至终 只要备用主库不故障 会一直提供读服务-->
                        <readHost host="c1-2-slave3308" url="192.168.20.12:3308" user="root" password="123456" />
                </writeHost> 
        </dataHost>  

        <dataHost name="mysqlcluster-2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                <heartbeat>select user()</heartbeat>  
                <writeHost host="c2-1-master3307" url="192.168.20.11:3307" user="root" password="123456">
                        <readHost host="c2-1-slave3309" url="192.168.20.11:3309" user="root" password="123456" />
                </writeHost> 
				<!--备用主库db3 主库db1故障后 开始提供写操作-->
                <writeHost host="c2-2-master3307" url="192.168.20.12:3307" user="root" password="123456">
						<!--备用主库的从库 从始至终 只要备用主库不故障 会一直提供读服务-->
                        <readHost host="c2-2-slave3309" url="192.168.20.12:3309" user="root" password="123456" />
                </writeHost> 
        </dataHost>  

</mycat:schema>

2)在Server配置文件中定义通过Mycat连接后允许访问的逻辑库

[root@mysql-1 ~]# vim /data/mycat/conf/server.xml
······
    <user name="root" defaultAccount="true">
        <!--登录用户的密码-->
        <property name="password">123456</property>
        <!--该用户登录后可以显示那些Schema-->
        <property name="schemas">TESTDB</property>
    </user>
······

2.3.重启Mycat

垂直分表策略规则配置完成后,下面就可以重启Mycat了。

[root@mysql-1 ~]# mycat restart
Stopping Mycat-server...
Mycat-server was not running.
Starting Mycat-server...

2.4.在Mycat命令行中导入数据结构

Mycat已经配置完垂直分表了,当有数据要写入到我们分的表时,对应的数据库实例上要保证这个库、表都存在,否则用户的数据将写入失败,无论是生产环境还是测试环境,使用Mycat分库分库后,需要先在分片节点上将数据库创建出来,然后再通过Mycat将不同的表划分存储到不同的分片节点上。

1)在两个分片节点中分别创建出db_shopping数据库

分片节点是双主双从集群,只需要连接上双主双从的任意一个主库上,创建数据库即可,会同步到所有的从库、主库上。

#分片1的主库操作
[root@mysql-1 sql]# mysql -uroot -p123456 -P3306 -h 192.168.20.11
mysql> create database db_shopping character set utf8mb4;

#分片2的主库操作
[root@mysql-1 sql]# mysql -uroot -p123456 -P3307 -h 192.168.20.11
mysql> create database db_shopping character set utf8mb4;

image-20220713222407220

2)登陆Mycat导入商品库的所有表以及数据

数据库需要在每个数据库实例上独立创建出来,数据表我们是通过Mycat进行垂直分表的,因此无需在每个实例上创建,只需要登陆Mycat,在Mycat中执行建表语句和插入数据,这时Mycat就会根据配置的分表策略,将不同的表写入到不同的数据库实例上。

当线上生产库要进行分表时,也是按照这种套路,在Mycat上执行多个表备份的数据,Mycat会自动路由到指定的数据库实例分片上。

[root@mysql-1 sql]# mysql -uroot -p123456 -P8066 -h 192.168.20.11
mysql> use db_shopping;
mysql> source /root/sql/shopping-table.sql
mysql> source /root/sql/shopping-insert.sql

2.5.查看由Mycat分表后每个分片上存储的表

我们一共有2个分片,每个分片都是双主双从的集群模式,我们只需要看每个分片的任意一个主库即可,因为从库会同步主库的数据,接下来我们去查看每个分片上所存储的商品库的表有那些,是否是我们规划的样子。

1)分片:mysqlcluster-1

查看该分片节点中的任意一个主库即可看到全部信息。

分片1:mysqlcluster-1包含了tb_goods_base、tb_goods_brand、tb_goods_cat、tb_goods_desc、tb_goods_item、tb_user、tb_user_address这7张表,垂直分表成功。

image-20220713224532691

2)分片:mysqlcluster-2

查看该分片节点中的任意一个主库即可看到全部信息。

分片2:mysqlcluster-2包含了tb_order_item、tb_order_master、tb_order_pay_log、tb_areas_city、tb_areas_region、tb_areas_provinces这6张表,垂直分表成功。

image-20220713224627802

2.6.Mycat垂直分表后可能遇到的问题

程序连接数据库,都是直接配置Mycat的地址,Mycat中的数据库、表都是逻辑性的,对于程序而言、开发同事而言,他们并不知道Mycat后端对应了那些数据库实例,并且当Mycat进行垂直分库、分表后,表与表之间可能都不在一个数据库实例上。

这时如果我们有多表联查的操作,可能联查的表与表并没有分在同一个数据库实例里,此时就会报错了,提示Mycat路由找不到对应的表,如下图所示:

image-20220713230543035

mysql> select ua.user_id, ua.contact, p.province, c.city, r.area , ua.address from tb_user_address ua ,tb_areas_city c , tb_areas_provinces p ,tb_areas_region r where ua.province_id = p.provinceid and ua.city_id = c.cityid and ua.town_id = r.areaid ;

tb_user_address、tb_areas_city这几张表都是在数据库中存在的,但是依旧报错说找不到该表,回想一下,在我们分库分表时,并没有将这两张表放在一个分片中,此时Mycat就不知道这两张表究竟位于哪一个分片中,因此就会报错找不到这张表。

image-20220713225756317

解决办法就是将要进行联查的表在Mycat分表时,设置成全局表,全局表会在指定的分片节点上创建,可以指定多个分片节点,并数据也是一样的,配置如下:

除了tb_user_address这张表以外,联查的其他表都在一个分片里,因此我们只对tb_user_address这张表设置全局表即可。

            <table name="tb_user_address" dataNode="dn1,dn2" type="global"/>

虽然指定了全局表,即使重启Mycat也不会生效,因为涉及到修改数据分布了,就需要将数据库实例上的库全部删除,然后重新备份还原,非常麻烦,因此建议一开始分库分表时,就将有联查动作的表划分到一个分片节点中,避免出错。

配置全局表后,重新删库导入表之后,在每个分片节点上都会存在全局表,全局表很鸡肋,后期设置需要重新刷Mycat配置,很麻烦,不建议使用,前期尽可能规划好。

image-20220713231748047

经过一系列删库还原,生效全局表后,联查成功。

image-20220713231409965

2.7.垂直分表完成

此时垂直分表已经完成了,说一些实战性的经验。

db_shopping库的部分表分在了分片节点1上,部分表分在分片节点2上,以后有新表创建时,如果没有在Mycat中为新表单独进行配置,默认会被分片到逻辑库关联的分片节点上。

如果对于新表就要求说存储在分片节点2上,那么在创建这张新表时,就在Mycat上配置好,然后重启Mycat,最后在Mycat上创建这张新表,字段路由到分片节点2上。

一定要最初就规划好每个分片锁存储的表,尽可能不使用全局表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1487693.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于JavaWEB SpringBoot婚纱影楼摄影预约网站设计和实现

基于JavaWEB SSM SpringBoot婚纱影楼摄影预约网站设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言…

两天学会微服务网关Gateway-Gateway工作原理

锋哥原创的微服务网关Gateway视频教程&#xff1a; Gateway微服务网关视频教程&#xff08;无废话版&#xff09;_哔哩哔哩_bilibiliGateway微服务网关视频教程&#xff08;无废话版&#xff09;共计17条视频&#xff0c;包括&#xff1a;1_Gateway简介、2_Gateway工作原理、3…

Vulnhub靶机:Bellatrix

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.4&#xff09; 靶机&#xff1a;Bellatrix&#xff08;10.0.2.9&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/hogwa…

【LangChain学习之旅】—(11) 记忆:通过Memory记住用户上次的对话细节

【LangChain学习之旅】—&#xff08;11&#xff09; 记忆&#xff1a;通过Memory记住客户上次买花时的对话细节 使用 ConversationChain使用 ConversationBufferMemory使用 ConversationBufferWindowMemory使用 ConversationSummaryMemory使用 ConversationSummaryBufferMemor…

VsCode搭建Spring Boot项目环境

VsCode搭建Spring Boot项目环境 1、前提条件&#xff1a;配置Java环境 下载安装JDK配置环境变量 2、VsCode配置SpringBoot环境 安装扩展 配置Maven 找到Maven配置文件&#xff0c;进行打开settings.json&#xff0c;添加如下代码&#xff1a; "workbench.iconThem…

码界深潜:全面解读软件工程的艺术与科学

&#x1f3e1; 基石构筑篇——软件工程基础理论及技能 &#x1f522; 编程语言选型与精修 于软件工程之浩瀚宇宙中&#xff0c;编程语言犹如各色画笔&#xff0c;每种语言的特性对应不同的创作领域。譬如Java倚仗跨平台兼容性和强大的面向对象机制&#xff0c;在企业级应用程序…

《GitHub新手入门指南:从零开始掌握基本用法》

在现代软件开发和技术社区中,GitHub已经成为了一个不可或缺的平台。它不仅是一个代码托管平台,更是一个技术交流、学习分享的社交平台。但对于初学者来说,GitHub可能会有些令人望而却步。本文将详细介绍GitHub的基本用法,帮助新手快速入门并融入这个充满活力的技术社区。 …

while 循环

语法格式&#xff1a; while (表达式) { 若干语句 } 执行规则 STEP1&#xff1a;计算表达式的值&#xff0c;如果 该值是true时&#xff0c;就进行STEP2&#xff0c; 否则执行STEP3。 STEP2&#xff1a;执行循环体&#xff0c;再进行 STEP1。 STEP3&#xff1a;结束while语句的…

WhatsApp API号注册平台价格对比:帮你选择性价比最高的服务

WhatsApp作为全球使用人数众多的即时通讯工具&#xff0c;推出的API服务为企业提供了强大的客户互动能力。然而面对众多提供WhatsApp API号注册的平台&#xff0c;企业在选择时很容易感到困惑。这篇文章将会对目前市面上比较主流的WhatsApp API号注册平台进行价格对比&#xff…

知识产权实缴注册资本的税务问题

2023年12月29日颁布的新《公司法》很快就要实施了。新《公司法》规定&#xff1a;公司注册资本需自公司成立之日起5年内缴足。因此&#xff0c;很多企业抓住政策的红利&#xff0c;通过知识产权实缴的方式实缴注册资本&#xff0c;这样可以不出现金就完成股东实缴注册资本的义务…

1.4 控制流程语句

1.4 控制流程语句 在C语言中&#xff0c;控制流程语句用于决定程序执行的流程。主要的控制流程语句包括条件语句和循环语句。 1.4.1 条件语句 条件语句允许根据条件的真假来执行不同的代码块。 1.4.1.1 if语句 if语句用于执行一个代码块&#xff0c;当给定的条件为真时执行…

Git 版本控制

Git 版本控制 1. About Version Control (关于版本控制)1.1. Local Version Control Systems (本地版本控制系统)1.2. Centralized Version Control Systems (集中化的版本控制系统)1.3. Distributed Version Control Systems (分布式版本控制系统) 2. 换行符的处理3. keyboard…

将一个时间序列中的每个元素转换为指定的日期格式

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将一个时间序列中的每个元素 转换为指定的日期格式 Series.dt.strftime() 选择题 以下关于代码输出结果的说法中正确的是? import pandas as pd ts pd.Series(pd.date_range("2024-03…

如何在 Java 中以编程的方式将 CSV 转为 Excel XLSX 文件

前言 Microsoft Excel的XLSX格式以及基于文本的CSV&#xff08;逗号分隔值&#xff09;格式&#xff0c;是数据交换中常见的文件格式。应用程序通过实现对这些格式的读写支持&#xff0c;可以显著提升性能。在本文中&#xff0c;小编将为大家介绍如何借助葡萄城公司地Java API…

数据结构c版(2)——二叉树

本章我们来了解一下二叉树这一概念。 目录 1.树概念及结构 1.1树的概念​​​​​​​ 1.2 树的特点&#xff1a; 1.3 树的相关概念 1.4 树的表示​​​​​​​ 1.5 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构 2.1概念 …

H3C接入交换机收到大量上行口(连接汇聚交换机)TC报文该怎么处理?(排查思路及解决办法)

一、问题描述 H3C接入交换机收到大量上行口的TC报文。 二、告警信息 三、TC报文排查思路 1、检查物理链路是否有问题。 2、检查是否有可能存在环路。 3、终端接入的端口开启STP边缘端口。 4、根桥的下联端口开启STP根保护。 5、如果对端设备不是管辖的范围且无法管理到,可考虑…

「优选算法刷题」:在每个树行中找最大值

一、题目 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,104]-231 < N…

WebSocket介绍+3分钟时间使用WebSocket搭建属自己的聊天室

WebSocket 的由来 在 WebSocket 出现之前&#xff0c;我们想实现实时通信、变更推送、服务端消息推送功能&#xff0c;我们一般的方案是使用 Ajax 短轮询、长轮询两种方式&#xff1a;比如我们想实现一个服务端数据变更时&#xff0c;立即通知客户端功能&#xff0c;没有 WebS…

【探索AI】二十一 深度学习之第4周:循环神经网络(RNN)与长短时记忆(LSTM)

循环神经网络&#xff08;RNN&#xff09;与长短时记忆&#xff08;LSTM&#xff09; RNN的基本原理与结构LSTM的原理与实现序列建模与文本生成任务实践&#xff1a;使用RNN或LSTM进行文本分类或生成任务步骤 1: 数据准备步骤 2: 构建模型步骤 3: 定义损失函数和优化器步骤 4: …

数字电路三宝:锁存器、寄存器和触发器

在数字电路设计中&#xff0c;很多电子工程师经常会用到锁存器、寄存器和触发器&#xff0c;它们各自承担着不同的功能&#xff0c;但共同为数字电路的稳定性和高效性提供了坚强保障&#xff0c;下面将谈谈这三大元件&#xff0c;希望对小伙伴们有所帮助。 1、锁存器&#xff0…