日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

滿懷憂思不如先干再說!
前言

數(shù)據(jù)庫拆分屬于中高級(jí)開發(fā)要做的事情,不過具體的看企業(yè)吧。各種情況都會(huì)出現(xiàn),這篇文章主要是基于Mycat去實(shí)現(xiàn)一下數(shù)據(jù)庫拆分,至于拆分的思想,后邊補(bǔ)一篇文章來說!本篇先簡(jiǎn)單介紹一下,至于優(yōu)缺點(diǎn)暫且不說,大家可以在操作或者閱讀的過程中自己先感受一下,大概分為兩種:

  • 垂直拆分:垂直分庫 和 垂直分表
  • 水平拆分:庫內(nèi)分表 和 分庫分表
分庫分表看起來很厲害的技術(shù),其實(shí)項(xiàng)目中來說的話可以不分庫分表還是不要分的好!
垂直拆分-分庫

 

垂直分庫就是根據(jù)業(yè)務(wù)耦合性,將關(guān)聯(lián)度低的不同表存儲(chǔ)在不同的數(shù)據(jù)庫。做法與大系統(tǒng)拆分為多個(gè)小系統(tǒng)類似,按業(yè)務(wù)分類進(jìn)行獨(dú)立劃分。與"微服務(wù)治理"的做法相似,每個(gè)微服務(wù)使用單獨(dú)的一個(gè)數(shù)據(jù)庫。


 

垂直拆分-分表

垂直分表是基于數(shù)據(jù)庫中的"列"進(jìn)行,某個(gè)表字段較多,可以新建一張擴(kuò)展表,將不經(jīng)常用或字段長度較大的字段拆分出去到擴(kuò)展表中。在字段很多的情況下(例如一個(gè)大表有100多個(gè)字段),通過"大表拆小表",更便于開發(fā)與維護(hù),也能避免跨頁問題,MySQL底層是通過數(shù)據(jù)頁存儲(chǔ)的,一條記錄占用空間過大會(huì)導(dǎo)致跨頁,造成額外的性能開銷。另外數(shù)據(jù)庫以行為單位將數(shù)據(jù)加載到內(nèi)存中,這樣表中字段長度較短且訪問頻率較高,內(nèi)存能加載更多的數(shù)據(jù),命中率更高,減少了磁盤IO,從而提升了數(shù)據(jù)庫性能。


 

水平拆分

當(dāng)一個(gè)應(yīng)用難以再細(xì)粒度的垂直切分,或切分后數(shù)據(jù)量行數(shù)巨大,存在單庫讀寫、存儲(chǔ)性能瓶頸,這時(shí)候就需要進(jìn)行水平切分了。

水平切分分為庫內(nèi)分表和分庫分表,是根據(jù)表內(nèi)數(shù)據(jù)內(nèi)在的邏輯關(guān)系,將同一個(gè)表按不同的條件分散到多個(gè)數(shù)據(jù)庫或多個(gè)表中,每個(gè)表中只包含一部分?jǐn)?shù)據(jù),從而使得單個(gè)表的數(shù)據(jù)量變小,達(dá)到分布式的效果。如圖所示:


 

庫內(nèi)分表只解決了單一表數(shù)據(jù)量過大的問題,但沒有將表分布到不同機(jī)器的庫上,因此對(duì)于減輕MySQL數(shù)據(jù)庫的壓力來說,幫助不是很大,大家還是競(jìng)爭(zhēng)同一個(gè)物理機(jī)的CPU、內(nèi)存、網(wǎng)絡(luò)IO,最好通過分庫分表來解決。

垂直拆分-分庫實(shí)現(xiàn)方式 配置mycat的schema配置文件 mysql" dbDriver="native" switchType="1" slaveThreshold="100"> select user() root" password="123456"> select user()

在兩個(gè)mysql實(shí)例中分別創(chuàng)建orders數(shù)據(jù)庫

CREATE DATABASE orders;

登陸Mycat創(chuàng)建四張表

-- 用戶表,假如有20W用戶 CREATE TABLE customer( id INT AUTO_INCREMENT, NAME varchar(20), PRIMARY KEY (id) ); -- 訂單表,假如有2000W個(gè)訂單 CREATE TABLE orders( id INT AUTO_INCREMENT, order_type INT, customer_id INT, amount DECIMAL(10,2), PRIMARY KEY (id) ); -- 訂單詳情表,數(shù)據(jù)量和訂單表一樣 CREATE TABLE order_detail( id INT AUTO_INCREMENT, detail VARCHAR(20), order_id INT, PRIMARY KEY (id) ); -- 字典表,數(shù)據(jù)量假如有20條,對(duì)應(yīng)訂單的類型字典,類型說明數(shù)字對(duì)應(yīng)字符串,訂單表中只需要存儲(chǔ)數(shù)字即可 CREATE TABLE dict_order_type( id INT AUTO_INCREMENT, order_type VARCHAR(20), PRIMARY KEY (id) );

查看表

如下圖,在Mycat上創(chuàng)建完之后Mycat窗口可以查詢出四張表,stt202上有一張customer表,stt203上有三張表,和我們理想效果一樣


 

水平拆分-分庫分表

我們發(fā)現(xiàn)order和order_detail兩張表中數(shù)據(jù)量非常多,如果存儲(chǔ)在同一個(gè)節(jié)點(diǎn)上的同一個(gè)庫中性能會(huì)受到影響,我們考慮將order表和order_detail表進(jìn)行拆分,分布式存儲(chǔ)全量數(shù)據(jù),平均存儲(chǔ)在兩臺(tái)節(jié)點(diǎn)上。

切片規(guī)則

 

  • 我們切分表中數(shù)據(jù)需要按照一定的規(guī)則切分,比如按照時(shí)間,id,用戶id等
  • 如果按照時(shí)間切分,老的數(shù)據(jù)存儲(chǔ)在一起,新的數(shù)據(jù)存儲(chǔ)在一起,用戶一般查詢的是新的數(shù)據(jù),所以會(huì)導(dǎo)致新數(shù)據(jù)所在節(jié)點(diǎn)的負(fù)載要高于舊數(shù)據(jù)節(jié)點(diǎn)
  • 如果按照id分區(qū)與日期效果類似,一樣會(huì)導(dǎo)致節(jié)點(diǎn)負(fù)載不均勻
  • 在本例中我們可以按照customer_id分配,具體的項(xiàng)目需求大家在具體考慮,盡可能讓數(shù)據(jù)平均分配,節(jié)點(diǎn)負(fù)載均衡

 

配置mycat的schema.xml配置文件

sqlschema="false" sqlMaxLimit="100" dataNode="dn1"> select user() select user()

配置rule.xml配置文件

customer_id mod-long 2

在dn2上創(chuàng)建orders表,重啟mycat,登陸mycat新增數(shù)據(jù)到orders表中

-- 我們以前添加,sql語法表名后的字段名可以省略,但是mycat分庫分表添加數(shù)據(jù)不可省略,因?yàn)樾枰该髂囊涣袛?shù)據(jù)是customer_id INSERT INTO orders(id,order_type,customer_id,amount)VALUES(1,101,100,100100); INSERT INTO orders(id,order_type,customer_id,amount)VALUES(2,101,100,100300); INSERT INTO orders(id,order_type,customer_id,amount)VALUES(3,101,101,120000); INSERT INTO orders(id,order_type,customer_id,amount)VALUES(4,101,101,103000); INSERT INTO orders(id,order_type,customer_id,amount)VALUES(5,102,101,100400); INSERT INTO orders(id,order_type,customer_id,amount)VALUES(6,102,100,100020);


 

 

通過上圖可以看出我們?cè)趍ycat中添加6條數(shù)據(jù),在mycat端可以全量查出,但是順序并不是按照id排序的,如果想要飄絮可以使用order by語句,在stt201和stt202上分別查出3條數(shù)據(jù),這樣就實(shí)現(xiàn)了數(shù)據(jù)的水平拆分

 

水平拆分的join關(guān)聯(lián)查詢


 

 

看上圖可以發(fā)現(xiàn)我們使用join內(nèi)關(guān)聯(lián)查詢時(shí)會(huì)提示說order_detail表找不到,我們對(duì)orders表進(jìn)行了切分也需要對(duì)orders的子表order_detail也進(jìn)行切分配置

 

schema.xml文件

在dn2上創(chuàng)建order_detail表,重啟mycat插入數(shù)據(jù)再做查詢

-- 插入數(shù)據(jù)和查詢都是在mycat端操作 -- 插入數(shù)據(jù) INSERT INTO order_detail(id,detail,order_id)VALUES(1,'detail',1); INSERT INTO order_detail(id,detail,order_id)VALUES(2,'detail',2); INSERT INTO order_detail(id,detail,order_id)VALUES(3,'detail',3); INSERT INTO order_detail(id,detail,order_id)VALUES(4,'detail',4); INSERT INTO order_detail(id,detail,order_id)VALUES(5,'detail',5); INSERT INTO order_detail(id,detail,order_id)VALUES(6,'detail',6); -- 連接查詢 SELECT * FROM orders o inner join order_detail od on o.id = od.order_id;


 

 

到此我們的垂直拆分和水平拆分就告一段落,當(dāng)然還沒有結(jié)束,真是XXXX了,咋還沒完心態(tài)炸裂,不慌大家老規(guī)矩喝杯茶繼續(xù)搞。

 

全局表

我們的業(yè)務(wù)表比如orders、order_detail表數(shù)據(jù)量很多時(shí)就需要切分,但是還一些附屬表,比如我們這里的dict_order_type(字典表),他們之間也要關(guān)聯(lián),字典表數(shù)據(jù)并不多,數(shù)據(jù)變動(dòng)不頻繁進(jìn)行切片就沒有必要,這種表Mycat中定義為全局表

特點(diǎn)

 

  • 全局表的插、更新操作會(huì)實(shí)時(shí)在所有節(jié)點(diǎn)上執(zhí)行,保持各個(gè)分片的一致性
  • 全局表的查詢操作,只從一個(gè)節(jié)點(diǎn)獲取
  • 全局表可以跟任意一個(gè)表進(jìn)行JOIN操作

 

修改schema.xml配置文件

保存在dn2上創(chuàng)建字典表,重啟mycat

INSERT INTO dict_order_type(id,order_type) VALUES(101,'type1'); INSERT INTO dict_order_type(id,order_type) VALUES(102,'type2');

 

我們查詢數(shù)據(jù)在dn1和dn2都有完整的兩條數(shù)據(jù),雖然存在數(shù)據(jù)冗余,但是好在這些表中的數(shù)據(jù)并不多,不用切分實(shí)現(xiàn)JOIN查詢

 

常用分片規(guī)則

我們?cè)谏线叺睦又星蟹謹(jǐn)?shù)據(jù)時(shí)使用的是取模切分,這里我們說一說其他開發(fā)中經(jīng)常用到的數(shù)據(jù)切分方式

枚舉分片

在配置文件中配置可能用到的枚舉ID,自己設(shè)置分片,比如按照省份或者區(qū)縣來做保存,而全國的省份區(qū)縣是固定的,可以使用在這些場(chǎng)景下

修改schema.xml配置文件

修改rule.xml配置文件

areacode hash-int ...... partition-hash-int.txt 1 0

修改partition-hash-int.txt配置文件

110=0 120=1

重啟mycat,創(chuàng)建表插入數(shù)據(jù)

-- 創(chuàng)建表 CREATE TABLE orders_ware_info( id INT AUTO_INCREMENT, order_id INT, address VARCHAR(20), areacode VARCHAR, PRIMARY KEY(id) ); -- 插入數(shù)據(jù) INSERT INTO orders_ware_info(id,order_id,address,areacode) VALUES (1,1,'北京','110'); INSERT INTO orders_ware_info(id,order_id,address,areacode) VALUES (2,2,'天津','120');


 

 

根據(jù)查詢結(jié)果在mycat上查詢是兩條數(shù)據(jù),在stt201上是北京,在stt202上是天津

 

范圍約定分片

比如我們的用戶id,將0-100000、100001-200000等這些按照范圍存儲(chǔ),適用于范圍提前規(guī)定好的場(chǎng)景,我們這里使用一張支付信息表為例

配置schema.xml文件

配置rule.xml配置文件

order_id rang-long ...... autopartition-long.txt 0

修改autopartition-long.txt文件

注意:將原本有的配置刪除

0-102 = 0 103-200=1

重啟mycat,創(chuàng)建表,插入數(shù)據(jù)

CREATE TABLE payment_info( id INT AUTO_INCREMENT, order_id INT, payment_status INT, PRIMARY KEY (id) ); INSERT INTO payment_info(id,order_id,payment_status) VALUES (1,101,0); INSERT INTO payment_info(id,order_id,payment_status) VALUES (2,102,1); INSERT INTO payment_info(id,order_id,payment_status) VALUES (3,103,0); INSERT INTO payment_info(id,order_id,payment_status) VALUES (4,104,1);


 

 

我們可以看到在mycat上查詢?nèi)繑?shù)據(jù),在stt201上展示兩條,在stt202上展示兩條,并且數(shù)據(jù)分布也正確

 

按照日期分片

我們按照天進(jìn)行劃分,設(shè)定時(shí)間格式、范圍

修改schema.xml配置文件

修改rule.xml配置文件

login_date shardingByDate ...... yyyy-MM-dd 2020-04-01 2020-04-04 2

重啟Mycat,創(chuàng)建表插入數(shù)據(jù)

CREATE TABLE login_info( id INT AUTO_INCREMENT, user_id INT, login_date date, PRIMARY KEY (id) ); INSERT INTO login_info(id,user_id,login_date) VALUES (1,101,'2020-04-01'); INSERT INTO login_info(id,user_id,login_date) VALUES (2,102,'2020-04-02'); INSERT INTO login_info(id,user_id,login_date) VALUES (3,103,'2020-04-03'); INSERT INTO login_info(id,user_id,login_date) VALUES (4,104,'2020-04-04'); INSERT INTO login_info(id,user_id,login_date) VALUES (5,103,'2020-04-05'); INSERT INTO login_info(id,user_id,login_date) VALUES (6,104,'2020-04-06');


 

 

看到效果,stt201上四條數(shù)據(jù)因?yàn)槌^結(jié)束日期重新開始分區(qū),stt202上兩條數(shù)據(jù),大家可以按照自己的想法去操作,看看是否和自己預(yù)想的效果一樣,好好體會(huì)體會(huì)!到此我們完成了基于Mycat的數(shù)據(jù)庫切分操作以及常用的切分方式作為參考

 

全局序列

在分庫分表的情況下,數(shù)據(jù)庫自增主鍵已無法保證自增主鍵的唯一性,為此Mycat提供了全局序列,提供了本地配置和數(shù)據(jù)庫配置多種實(shí)現(xiàn)方式

本地文件

此方式Mycat將sequence配置到文件中,當(dāng)使用到sequence中的配置后,Mycat會(huì)更新該值

 

  • 優(yōu)勢(shì):本地加載,讀取速度較快
  • 弊端:抗風(fēng)險(xiǎn)性差,mycat宕機(jī)無法讀取配置文件,重啟之后序列會(huì)重新開始,造成重復(fù)

 

數(shù)據(jù)庫方式(推薦使用)

利用數(shù)據(jù)庫的一個(gè)表來進(jìn)行累加,并不是每次生成序列都讀寫數(shù)據(jù)庫,這樣太慢,Mycat會(huì)預(yù)先加載一部分到Mycat內(nèi)存中,這樣大部分讀寫都在內(nèi)存中完成,如果內(nèi)存中號(hào)段用完Mycat再向數(shù)據(jù)庫要一次

在dn1上創(chuàng)建MYCAT_SEQUENCE序列表

CREATE TABLE MYCAT_SEQUENCE ( name VARCHAR(50) NOT NULL, current_value INT NOT NULL, increment INT NOT NULL DEFAULT 100, PRIMARY KEY(name) )ENGINE=InnoDB;

創(chuàng)建函數(shù)獲取當(dāng)前sequence的值

DELIMITER $ CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN DECLARE retval VARCHAR(64); SET retval="-999999999,null"; SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR)) INTO retval FROM MYCAT_SEQUENCE WHERE name = seq_name; RETURN retval; END $ DELIMITER ;

創(chuàng)建函數(shù)設(shè)置sequence的值

DELIMITER $ CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name; RETURN mycat_seq_currval(seq_name); END $ DELIMITER ;

創(chuàng)建函數(shù)獲取下一個(gè)sequence的值

DELIMITER $ CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment WHERE name = seq_name; RETURN mycat_seq_currval(seq_name); END $ DELIMITER ;

初始化序列表

-- 新增一條數(shù)據(jù),序列名為ORDERS,初始值為400000,increment100,這個(gè)設(shè)置的是Mycat重啟之后的值遞增100,這個(gè)大家根據(jù)業(yè)務(wù)自己設(shè)置 INSERT INTO MYCAT_SEQUENCE(NAME,current_value,increment) VALUES('ORDERS',400000,100);

修改schmea.xml文件

修改Mycat的sequence_db_conf.properties文件

前邊為序列名后邊為所在節(jié)點(diǎn),我們序列名為ORDERS就是在dn1上創(chuàng)建的,如果你是在dn2上創(chuàng)建的序列表,則改為dn2

#sequence stored in datanode GLOBAL=dn1 COMPANY=dn1 CUSTOMER=dn1 ORDERS=dn1

修改server.xml文件


 

把改為1,配置使用序列的哪種方式,Mycat提供了三種方式,0為本地文件,1為數(shù)據(jù)庫方式,2為時(shí)間戳方式

添加數(shù)據(jù)

語法就是將ID的值改為next value for MYCATSEQ_SeqName咱們這里的序列名為ORDERS。

INSERT INTO orders(id,order_type,customer_id,amount) VALUES (next value for MYCATSEQ_ORDERS,101,102,1000);

查詢數(shù)據(jù)

SELECT * FROM orders;


 

時(shí)間戳方式

全局序列ID=64位二進(jìn)制(42(毫秒)+5(機(jī)器ID)+5(業(yè)務(wù)編碼)+12(重復(fù)累加))換算成十進(jìn)制為18位的long類型,每毫秒可以并發(fā)12位二進(jìn)制累加

 

  • 優(yōu)勢(shì):配置簡(jiǎn)單
  • 弊端:太長

 

自主生成

可以在項(xiàng)目中自己編寫生成序列的代碼,或者使用redis的incr生成序列,這種方式也行但是需要在程序中進(jìn)行編碼,我們還是推薦使用Mycat自帶的全局序列,也就是第二種方式

總結(jié)

 

  • 實(shí)現(xiàn)制定好切分方式或者說切分計(jì)劃
  • 準(zhǔn)備好物理Mysql,這些Mysql應(yīng)該都是白白的很干凈的
  • 安裝好Mycat,配置Mycat的配置文件
  • 啟動(dòng)Mycat創(chuàng)建表插入數(shù)據(jù)等操作,通過Mycat會(huì)將表和數(shù)據(jù)創(chuàng)建并且插入到真正的物理MySQL中維護(hù)
  • Mycat提供三種全局序列,解決分布式數(shù)據(jù)庫主鍵ID唯一問題,我們使用數(shù)據(jù)庫方式

 

覺得不錯(cuò)的話,記得動(dòng)動(dòng)小手關(guān)注,收藏哦,本文若有任何看不懂,或者有錯(cuò)誤的地方歡迎大家評(píng)論區(qū)留言!

分享到:
標(biāo)簽:MySQL
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定