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

文章目录

    • 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.rhkb.cn/news/268487.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件测试项目实战,某购物车/测试点分析实战(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 第一步&#xff1…

winform 输出运行设备的mac地址

winform定制一个代码段 输出运行设备的mac码此方法获取的是运行设备上的物理网卡的MAC地址&#xff0c;并不包括虚拟网卡或无线网卡的MAC地址。当设备具有多个网卡时&#xff0c;它只返回第一个正常运行的网卡的MAC地址。如果未找到任何网卡&#xff0c;则返回"未找到MAC地…

贪心(基础算法)--- 区间选点

905. 区间选点 思路 &#xff08;贪心&#xff09;O(nlogn) 根据右端点排序 将区间按右端点排序 遍历区间&#xff0c;如果当前区间左端点不包含在前一个区间中&#xff0c;则选取新区间&#xff0c;所选点个数加1&#xff0c;更新当前区间右端点。如果包含&#xff0c;则跳…

雅特力AT32L021首款低功耗MCU震撼登场

雅特力于2月28日正式发布AT32L021首款入门级低功耗MCU&#xff0c;搭配不同容量Flash、SRAM&#xff0c;提供7种封装类型共21个型号选择&#xff0c;最小封装面积仅3x3mm。为降低能耗&#xff0c;延长设备运作时间&#xff0c;AT32L021系列支持多种能耗模式和休眠模式&#xff…

韦东山嵌入式Liunx入门驱动开发五

文章目录 一、驱动程序基石1-1 休眠与唤醒1-2 POLL机制1-3 异步通知(1) 异步通知程序解析(2) 异步通知机制内核代码详解 1-4 阻塞与非阻塞1-5 定时器(1) 内核函数(2) 定时器时间单位 1-6 中断下半部 tasklet 本人学习完韦老师的视频&#xff0c;因此来复习巩固&#xff0c;写以…

【活动】前端世界的“祖传代码”探秘:从古老魔法到现代重构

作为一名前端工程师&#xff0c;我时常在项目中邂逅那些被岁月打磨过的“祖传代码”。它们就像古老的魔法书页&#xff0c;用HTML标签堆砌起的城堡、CSS样式表中的炼金术&#xff0c;以及JavaScript早期版本中舞动的符咒。这些代码承载着先驱们的探索精神和独特智慧&#xff0c…

#FPGA(基础知识)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;正点原子-verilog基础知识 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a;

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

【Git】深入理解 Git 分支合并操作:git merge dev 命令详解

深入理解 Git 合并操作&#xff1a;git merge dev 命令详解 摘要&#xff1a;本文将深入探讨 Git 中的合并操作&#xff0c;以及如何使用 git merge dev 命令将dev 分支的修改合并到当前分支&#xff08;假设当前分支为main 分支&#xff09;中。通过详细的解释和示意图&#x…

linux安全--DNS欺骗,钓鱼网站搭建

目录 一&#xff0c;实验准备 首先让client能上网 1&#xff09;实现全网互通&#xff0c;实现全网互通过程请看 2&#xff09;SNAT源地址转换 3&#xff09;部署DHCP服务 4)配置DHCP服务 5&#xff09;启动服务 6&#xff09;安装DNS服务 7&#xff09;DNS配置 8)启动DNS…

HOOPS Communicator对3D大模型轻量化加载与渲染的4种解决方案

今天给大家介绍一些关于3D Web轻量化引擎HOOPS Commuicator的关键概念&#xff0c;这些概念可以帮您在HOOPS Communicator流缓存服务器之上更好地构建您自己的模型流服务器。如果您是有大型数据集&#xff0c;那么&#xff0c;使用流缓存服务器可以极大地帮助您最大限度地减少内…

Unity 预制体与变体

预制体作用&#xff1a; 更改预制体&#xff0c;则更改全部的以预制体复制出的模型。 生成预制体&#xff1a; 当你建立好了一个模型&#xff0c;从层级拖动到项目中即可生成预制体。 预制体复制模型&#xff1a; 将项目中的预制体拖动到层级中即可复制。或者选择物体复制粘贴。…

Java基础 - 6 - 面向对象(二)

Java基础 - 6 - 面向对象&#xff08;一&#xff09;-CSDN博客 二. 面向对象高级 2.1 static static叫做静态&#xff0c;可以修饰成员变量、成员方法 2.1.1 static修饰成员变量 成员变量按照有无static修饰&#xff0c;分为两种&#xff1a;类变量、实例变量&#xff08;对象…

VL53L8CX驱动开发(1)----驱动TOF进行区域检测

VL53L8CX驱动开发----1.驱动TOF进行区域检测 概述视频教学样品申请源码下载主要特点硬件准备技术规格系统框图应用示意图区域映射生成STM32CUBEMX选择MCU 串口配置IIC配置LPn 设置X-CUBE-TOF1串口重定向代码配置Tera Term配置演示结果 概述 VL53L8CX是一款8x8多区域ToF测距传感…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--强化学习

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 分类: 大语言模型LLM视觉模型VLM扩散模型视觉…

Git分布式版本控制系统——git学习准备工作

一、Git仓库介绍 开发者可以通过Git仓库来存储和管理文件代码&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库 远程仓库&#xff1a;远程服务器上的Git仓库 仓库之间的运转如下图&#xff1a; commit&#xff1a;提交&#xff…

linux 搭建web网站

综合练习&#xff1a;请给openlab搭建web网站 网站需求&#xff1a; 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[www.openlab.…

从零开始,使用C语言实现扫雷小游戏

扫雷 1. 前言2. 准备工作3. 设计思路4. 定义数组5. 初始化6. 打印7. 布置雷8. 排查雷9. 完整代码 1. 前言 大家好&#xff0c;我是努力学习游泳的鱼。今天我们会用C语言实现一个经典的windows小游戏&#xff1a;扫雷。扫雷是一款单机小游戏&#xff0c;我上中学时特喜欢在电脑…

PHP【swoole】

前言 Swoole官方文档&#xff1a;Swoole 文档 Swoole 使 PHP 开发人员可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务&#xff0c;让 PHP 不再局限于 Web 领域。Swoole4 协程的成熟将 PHP 带入了前所未有的时期&#xff0c; 为性能的提升提供了独一无…

springboot197基于springboot的毕业设计系统的开发

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的毕业设计系统的开发 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 …