第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.pswp.cn/news/718610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718610.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Unity編輯器下如何獲取物體(GameObject)的中心位置

注意僅能在編輯器下才能使用該方法 實現方式依靠UnityEditor.Tools提供的參數&#xff0c;具體實現如下&#xff1a; 獲取單個物體的中心坐標 public static Vector3 GetGameObjectCenter(GameObject gameObject) {// 選中物體Selection.activeObject gameObject;// 記錄當前…

C#中Byte.Parse的用法,如果需要解析含有數字以外的字符,應該如何使用?

在C#中&#xff0c;Byte.Parse用于將字符串解析為byte類型的數字。它的用法如下&#xff1a; byte result Byte.Parse(str);其中&#xff0c;str是要解析的字符串。 如果要解析的字符串含有數字以外的字符&#xff0c;Byte.Parse會拋出一個FormatException異常。為了處理這種…

javaWebssh水利綜合信息管理系統myeclipse開發mysql數據庫MVC模式java編程計算機網頁設計

一、源碼特點 java ssh水利綜合信息管理系統是一套完善的web設計系統&#xff08;系統采用ssh框架進行設計開發&#xff09;&#xff0c;對理解JSP java編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統主要采用B/S模式開發。開發環境為TOMCA…

MATLAB 實現貝葉斯決策

1. 原理 后驗概率&#xff1a; 1.最小錯誤率決策&#xff08;最大后驗概率決策&#xff09;&#xff1a; 2.最小風險決策&#xff1a; 3.正態分布下的貝葉斯決策 2. 過程 2.1 訓練集數據可視化 導入兩類訓練集數據&#xff0c;并繪制其數據分布&#xff0c;如下&#xff1a;…

云時代【5】—— LXC 與 容器

云時代【5】—— LXC 與 容器 三、LXC&#xff08;一&#xff09;基本介紹&#xff08;二&#xff09;相關 Linux 指令實戰&#xff1a;使用 LXC 操作容器 四、Docker&#xff08;一&#xff09;刪除、安裝、配置&#xff08;二&#xff09;鏡像倉庫1. 分類2. 相關指令&#xf…

JavaSE-09(Java IO精華總結)

Java IO 簡單做個總結&#xff1a; 1 .InputStream/OutputStream 字節流的抽象類。2 .Reader/Writer 字符流的抽象類。3 .FileInputStream/FileOutputStream 節點流&#xff1a;以字節為單位直接操作“文件”。4 .ByteArrayInputStream/ByteArrayOutputStream 節點流&#xff…

Running job: job_1709516801756_0003

** yarn運行卡在Running job: job_1709516801756_0003問題解決&#xff1a; ** 在運行wordcount時出現錯誤&#xff0c;一直卡住 運行命令&#xff1a;hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output 出現錯誤&#xff1a…

嶺回歸算法

回歸分析方法是利用數理統計方法分析數據&#xff0c;建立自變量和因變量間的回歸模型&#xff0c;用于預測因變量變化的分析方法。其中比較經典的是HoerI和Kennard提出的嶺回歸算法。嶺回歸算法是在最小二乘法的基礎上引|入正則項&#xff0c;使回歸模型具有較好泛化能力和穩定…

經典思路!人參葉際微生物如何發8分文章?

中國中醫科學院中藥研究所在《Environmental Microbiome》期刊上(IF7.9)發表了關于葉際真菌微生態網絡的文章&#xff0c;該研究通過對ITS測序結果和環境因子測定結果以及皂苷含量測定結果進行生信分析&#xff0c;提出了維持微生態網絡的穩定性策略和影響皂苷含量的因素。 期刊…

H12-821_113

113.如圖所示是路由器現ATE輸出的部分信息&#xff0c;以下關于這部分信息的描述&#xff0c;錯誤的是哪一項&#xff1f; A.display pim rp-info命令用來查看組播組對應的RP信息 B.RP地址是2.2.2.2 C.組地址是225.0.0.0 D.RP的優先級是0 答案&#xff1a;C 注釋&#xff1a; …

HCIA-Datacom題庫(自己整理分類的)_29_PPP協議判斷【6道題】

1.數據鏈路層采用PPP封裝鏈路兩端的IP地址可以不在同一個網段。√ 2.PPP鏈路兩端不在同一網段不能通信。 3.參考以下拓撲及配置&#xff0c;路由器R1與R2通過Serial低速線纜連接&#xff0c;且數據鏈路層封裝使用PPP。當R1和R2的Holdtime不一致時&#xff0c;PPP協商失敗&…

python使用常用的路徑問題

PythonPath多個路徑的使用 通過命令行直接修改 export PYTHONPATH$PYTHONPATH:/path/to/directoryPythonPath多個路徑的使用 export PYTHONPATH$PYTHONPATH:/path/to/directory1:/path/to/directory2PythonPath多個路徑的使用 python path 移除路徑 python path python中…

爬蟲實戰——麻省理工學院新聞

文章目錄 發現寶藏一、 目標二、 淺析三、獲取所有模塊四、請求處理模塊、版面、文章1. 分析切換頁面的參數傳遞2. 獲取共有多少頁標簽并遍歷版面3.解析版面并保存版面信息4. 解析文章列表和文章5. 清洗文章6. 保存文章圖片 五、完整代碼六、效果展示 發現寶藏 前些天發現了一…

jQuery AJAX get() 和 post() 方法—— W3school 詳解 簡單易懂(二十四)

jQuery get() 和 post() 方法用于通過 HTTP GET 或 POST 請求從服務器請求數據。 HTTP 請求&#xff1a;GET vs. POST 兩種在客戶端和服務器端進行請求-響應的常用方法是&#xff1a;GET 和 POST。 GET - 從指定的資源請求數據POST - 向指定的資源提交要處理的數據 GET 基本…

MySQL面試題-日志(答案版)

日志 1、為什么需要 undo log&#xff1f; &#xff08;1&#xff09;實現事務回滾&#xff0c;保障事務的原子性。 事務處理過程中&#xff0c;如果出現了錯誤或者用戶執 行了 ROLLBACK 語句&#xff0c;MySQL 可以利用 undo log 中的歷史數據將數據恢復到事務開始之前的狀態…

ssh無法直接登入Linux超級用戶root(23/3/3更新)

說明&#xff1a;不允許ssh用超級用戶的身份登入是為了安全性&#xff0c;如果只是學習使用對安全性沒啥要求可以按以下操作解除限制 以普通用戶登錄到服務器后&#xff0c;執行以下命令以編輯 SSH 服務器配置文件 /etc/ssh/sshd_config sudo nano /etc/ssh/sshd_config 此時會…

【C++練級之路】【Lv.10】【STL】priority_queue類和反向迭代器的模擬實現

快樂的流暢&#xff1a;個人主頁 個人專欄&#xff1a;《C語言》《數據結構世界》《進擊的C》 遠方有一堆篝火&#xff0c;在為久候之人燃燒&#xff01; 文章目錄 一、仿函數1.1 仿函數的介紹1.2 仿函數的優勢 二、priority_queue2.1 push2.2 pop2.3 top2.4 size2.5 empty 三、…

【3D Slicer】心臟CT圖像分割操作保姆級教程 Cardiac CT image segmentation

心臟CT圖像分割操作流程指南 1 安裝3D Slicer軟件2 打開文件2.1 從File->Add Data->Choose File2.2 直接拖入 3 進行分割操作4 切片填充 Fill between slices5 第二個例子6 數據保存7 打開保存后的文件 1 安裝3D Slicer軟件 方式二選一 1.官網&#xff1a;3D Slicer 2.百…

JNI方案說明和使用方法介紹

JNI簡介 JNI(Java Native Interface)是Java編程語言中用于實現Java代碼與本地(Native)代碼(通常是C或C++代碼)交互的機制。它允許Java應用程序調用本地代碼中的功能,也可以讓本地代碼調用Java類和方法。JNI在Java平臺上實現了Java與其他編程語言的互操作性。(即可互相…

無字母數字rce總結(自增、取反、異或、或、臨時文件上傳)

目錄 自增 取反 異或 或 臨時文件上傳 自增 自 PHP 8.3.0 起&#xff0c;此功能已軟棄用 在 PHP 中&#xff0c;可以遞增非數字字符串。該字符串必須是字母數字 ASCII 字符串。當到達字母 Z 且遞增到下個字母時&#xff0c;將進位到左側值。例如&#xff0c;$a Z; $a;將…