mycat的使用

mycat:數據庫中間件

由于mycat的團隊過于惡心,所以不建議使用mycat,可以轉為使用shardding JDBC

為什么要用mycat? mycat解決一下三個問題
  • 解決了Java應用與數據緊耦合的問題
  • 緩解了高訪問量高并發的壓力
  • 解決了讀寫請求數據不一致的問題
mycat主要做的事
  • 讀寫分離


    image.png
  • 數據分片:垂直拆分(分庫)、水平拆分(分表)、垂直+水平拆分(分庫分表)


    image.png
  • 多數據源整合


    image.png
mycat原理

Mycat 的原理中最重要的一個動詞是“攔截”,它攔截了用戶發送過來的 SQL 語句,首先對 SQL 語句做了一些特定的分析:如分片分析、路由分析、讀寫分離分析、緩存分析等,然后將此 SQL 發往后端的真實數據庫,并將返回的結果做適當的處理,最終再返回給用戶。這種方式把數據庫的分布式從代碼中解耦出來,程序員察覺不出來后臺使用 Mycat 還是MySQL。

image.png
mycat安裝

上傳壓縮安裝包到服務器上
然后解壓到/usr/local目錄下
tar -zxvf Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz -C /usr/local/
去/usr/local/mycat/conf目錄下編輯 server.xml 和schema.xml文件。

image.png

注意:這里的TESTDB指的是mycat邏輯庫,并不是真正的庫
image.png

確保兩臺機器都安裝好mysql并且可以遠程登錄
mysql -umysqlu1 -p12345678 -h 192.168.107.135 -P 3306
mysql -umysqlu1 -p12345678 -h 192.168.107.135 -P 3306

啟動mycat
  • 控制臺啟動 :去 /usr/local/mycat/bin 目錄下執行 ./mycat console
  • 后臺啟動 :去 /usr/local/mycat/bin 目錄下 ./mycat start
登錄mycat
  • 登錄后臺管理窗口(這個方法用于管理維護mycat)
    mysql -umycat -p123456 -P 9066 -h 192.168.107.135


    image.png
  • 登錄數據窗口(這個方式用于通過mycat查詢數據)
    mysql -umycat -p123456 -P 8066 -h 192.168.107.135


    image.png
搭建mysql主從復制 (一主一從)

修改主機配置文件

修改配置文件:vim /etc/my.cnf
#主服務器唯一ID
server-id=1
#啟用二進制日志
log-bin=mysql-bin
# 設置不要復制的數據庫(可設置多個)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#設置需要復制的數據庫
binlog-do-db=testdb
#設置logbin格式
binlog_format=STATEMENT

上面的logbin格式格外重要,分三種模式 STATEMENT,ROW,MIXED。各有優缺點,具體可以去網上看https://www.cnblogs.com/xingyunfashi/p/8431780.html

修改從機配置文件

修改配置文件:vim /etc/my.cnf
#從服務器唯一ID
server-id=2
#啟用中繼日志
relay-log=mysql-relay

重啟主機和從機的mysql服務
systemctl restart mysqld
查看重啟后的mysql狀態
systemctl status mysqld

在主機上創建一個用戶,用于從機來復制數據

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '12345678';

(命令解釋:創建一個在所有庫所有表都有主從復制權限的遠程訪問用戶 ,用戶名為slave,密碼為123123)

查看主機master狀態,在此之后 主機別操作了,防止主機狀態值變化。
show master status;


image.png

記下File 和 Position的值

在從機上配置需要復制的主機,(進入mysql從機命令行 輸入以下命令)

CHANGE MASTER TO MASTER_HOST='192.168.107.135',
MASTER_USER='slave',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.mysql-bin.000002',MASTER_LOG_POS=154;
image.png

啟動從服務器復制功能
start slave;
查看服務器狀態,下面兩個都是yes才表示成功,如果有No,則下面的error行會報錯原因。
show slave status\G;


image.png

如果從機已經配置過主機,那么我們可以reset 主機;
先 stop slave; 然后reset master; 然后再執行上面的語句。

現在我們在主機里新建testdb庫(僅僅是testdb庫 建表 建數據,其他不行 因為前面配置了只復制testdb這個庫),然后看看從機是否有響相應的復制數據。

配置mycat讀寫分離,負載均衡類型,目前的取值有4 種:

(1)balance="0", 不開啟讀寫分離機制,所有讀操作都發送到當前可用的 writeHost 上。
(2)balance="1",全部的 readHost 與 stand by writeHost 參與 select 語句的負載均衡,簡單的說,當雙主雙從
模式(M1->S1,M2->S2,并且 M1 與 M2 互為主備),正常情況下,M2,S1,S2 都參與 select 語句的負載均衡。
(3)balance="2",所有讀操作都隨機的在 writeHost、readhost 上分發。
(4)balance="3",所有讀請求隨機的分發到 readhost 執行,writerHost 不負擔讀壓力
這里的配置,如果是一主一從,配置3就可以了,如果是多主(多主之間互為主備)多從,配置1就行了
這里我們可以驗證mycat 的select路由功能了

搭建mysql主從復制 (多主多從)。這里搭建二主二從

一個主機 m1 用于處理所有寫請求,它的從機 s1 和另一臺主機 m2 還有它的從機 s2 負責所有讀請求。當 m1 主機宕機后,m2 主機負責寫請求,m1、m2 互為備機,這里m1 和m2 的地位是一樣的。架構圖如下

image.png

我們這里是mysql服務器情況是
135 master1
129 master2
136 slave1
130 slave2
136 復制 135, 130 復制 129,129 和 135互相復制

依次關閉四臺mysql服務,編輯mysql配置 vim /etc/my.cnf
master1的配置如下

#主服務器唯一ID
server-id=1
#啟用二進制日志
log-bin=mysql-bin
# 設置不要復制的數據庫(可設置多個)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#設置需要復制的數據庫
binlog-do-db=testdb
#設置logbin格式
binlog_format=STATEMENT

# 在作為從數據庫的時候,有寫入操作也要更新二進制日志文件
log-slave-updates 
#表示自增長字段每次遞增的量,指自增字段的起始值,其默認值是1,取值范圍是1 .. 65535
auto-increment-increment=2 
# 表示自增長字段從哪個數開始,指字段一次遞增多少,他的取值范圍是1 .. 65535
auto-increment-offset=1

master2的配置如下

#主服務器唯一ID
server-id=3 #啟用二進制日志
log-bin=mysql-bin
# 設置不要復制的數據庫(可設置多個)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#設置需要復制的數據庫
binlog-do-db=testdb
#設置logbin格式
binlog_format=STATEMENT

# 在作為從數據庫的時候,有寫入操作也要更新二進制日志文件
log-slave-updates 
#表示自增長字段每次遞增的量,指自增字段的起始值,其默認值是1,取值范圍是1 .. 65535
auto-increment-increment=2 
# 表示自增長字段從哪個數開始,指字段一次遞增多少,他的取值范圍是1 .. 65535
auto-increment-offset=2 #  這里從2開始,不能和master1重復

slave1配置

#從服務器唯一ID
server-id=2
#啟用中繼日志
relay-log=mysql-relay

slave2配置

#從服務器唯一ID
server-id=4
#啟用中繼日志
relay-log=mysql-relay

雙主機、雙從機重啟 mysql 服務,主機從機都關閉防火墻。在兩臺主機建立授權slave賬戶

GRANT REPLICATION SLAVE ON . TO 'slave'@'%' IDENTIFIED BY '12345678';

查看m1 ,m2 狀態,記下 File和Position


image.png

image.png

在兩臺從機配置 執行復制主機的動作。

#136 復制 135
CHANGE MASTER TO MASTER_HOST='192.168.107.135',
MASTER_USER='slave',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.mysql-bin.000005',MASTER_LOG_POS=1254;

#在130 復制 129 
CHANGE MASTER TO MASTER_HOST='192.168.107.129',
MASTER_USER='slave',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.mysql-bin.000001',MASTER_LOG_POS=6271;

兩臺從服務器均執行 start slave ; 然后查看slave狀態,均為YES則表示設置成功。


image.png
image.png

兩主互相復制

# 129 復制 135
CHANGE MASTER TO MASTER_HOST='192.168.107.135',
MASTER_USER='slave',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.mysql-bin.000005',MASTER_LOG_POS=1254;

# 135復制 129 
CHANGE MASTER TO MASTER_HOST='192.168.107.129',
MASTER_USER='slave',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.mysql-bin.000001',MASTER_LOG_POS=6271;

現在可以在主庫中 建庫 建表 建數據,驗證雙主雙從是否配置成功了。

配置mycat雙主雙從讀寫分離

相比之前的一主一從配置,我們這里需要增加一對host主從配置

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">

        </schema>
        <dataNode name="dn1" dataHost="host1" database="testdb" />

        <dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.107.135:3306" user="mysqlu1" password="12345678">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="192.168.107.136:3306" user="mysqlu1" password="12345678" />
                </writeHost>

                <writeHost host="hostM2" url="192.168.107.129:3306" user="mysqlu1" password="12345678">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="192.168.107.130:3306" user="mysqlu1" password="12345678" />
                </writeHost>

        </dataHost>
</mycat:schema>

相關配置解釋

# balance="1": 全部的readHost與stand by writeHost參與select語句的負載均衡。
#writeType="0": 所有寫操作發送到配置的第一個writeHost,第一個掛了切到還生存的第二個
#writeType="1",所有寫操作都隨機的發送到配置的 writeHost,1.5 以后廢棄不推薦
#writeHost,重新啟動后以切換后的為準,切換記錄在配置文件中:dnindex.properties 。
 #switchType="1": 1 默認值,自動切換。   -1 表示不自動切換,  2 基于 MySQL 主從同步的狀態決定是否切換。

驗證mycat讀寫分離,登錄mycat,從查詢結果可以看出來,mycat查詢是在2從一備份主之一執行查詢的。
mysql -umycat -p123456 -P 8066 -h 192.168.107.135


image.png

驗證可用性:任意關閉一臺主mysql服務器,數據依然可以插入,依然可以查詢數據,主服務器重啟后,該臺服務器依然會同步最新數據,只是現在這個服務器的角色肯定是主寫服務器的備用服務器,不管它之前是主寫服務器還是主服務器的備用服務器。

這種配置有一個問題,當任意一臺主服務器掛掉的時候(比如m2),那么對于mycat來說 其實就等于掛掉兩臺服務器,因為s2也相當于也掛了,因為s2 找不到它的m2。 這毫無疑問肯定是不合理的。這里如果對s2自動做主從切換就好了 就是redis哨兵一樣。

垂直拆分-分庫

一個數據庫由很多表的構成,每個表對應著不同的業務,垂直切分是指按照業務將表進行分類,分布到不同的數據庫上面,這樣也就將數據或者說壓力分擔到不同的庫上面。
要明確的是:在mysql的join操作中,如果兩個表位于不同主機上的庫中,那么join操作是不可執行的,如果位于同一個主機的不同庫中 join是可以執行的, 我們這里后續指的 "分庫","不同庫" 等概念, 指的就是位于不同主機上的庫,分庫的總體原則是有業務關聯關系的表應該放在一個庫里,相互沒有關聯關系的表放在不同庫里。
這里我們準備四張表 customer 客戶表,orders 訂單表,orders_detail 訂單詳情表,dict_order_type 訂單字典表,我們客戶表放一個庫里,其他的表放一個庫里。
mycat 配置如下

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <!-- 這里schema配置的意思是 操作customer表的時候 那么就走dn2節點查詢,否則走dn1節點  -->
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
                <table name="customer" dataNode="dn2" ></table>
        </schema>
        <dataNode name="dn1" dataHost="host1" database="orders" />
        <dataNode name="dn2" dataHost="host2" database="orders" />

        <dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.107.135:3306" user="mysqlu1" password="12345678">

                </writeHost>
        </dataHost>

        <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM2" url="192.168.107.129:3306" user="mysqlu1" password="12345678">

                </writeHost>
        </dataHost>

</mycat:schema>

我們現在先在135和129服務器上新建orders數據庫

CREATE DATABASE orders;

啟動mycat 并訪問mycat

/usr/local/mycat/bin/mycat console
mysql -umycat -p123456 -P 8066 -h 192.168.107.135

在mycat命令行下執行建庫操作,建庫語句如下

#客戶表 
CREATE TABLE customer(
 id INT AUTO_INCREMENT,
 NAME VARCHAR(200),
 PRIMARY KEY(id)
);
#訂單表 
CREATE TABLE orders(
 id INT AUTO_INCREMENT,
 order_type INT,
 customer_id INT,
 amount DECIMAL(10,2),
 PRIMARY KEY(id) 
); 
#訂單詳細表 
CREATE TABLE orders_detail(
 id INT AUTO_INCREMENT,
 detail VARCHAR(2000),
 order_id INT,
 PRIMARY KEY(id)
);
#訂單狀態字典表 
CREATE TABLE dict_order_type(
 id INT AUTO_INCREMENT,
 order_type VARCHAR(200),
 PRIMARY KEY(id)
);

然后切換到各自mysql控制臺,可以看到相應的表已經建立在相應的數據上了,并且可以在相應的數據庫上新增數據 ,查詢數據等等,就這樣分庫成功了。

水平拆分-分表

MySQL單表存儲數據條數是有瓶頸的,單表達到1000萬條數據就達到了瓶頸,會影響查詢效率,需要進行水平拆分(分表)進行優化。我們以orders表為例子來分表。

關于分表策略: 對于我們orders表來說 如果以id來分表的話,查詢訂單注重時效,歷史訂單被查詢的次數少,如此分片會造成一個節點訪問多,一個訪問少,不平均。如果以customer_id來分的話,根據客戶id去分,兩個節點訪問平均,一個客戶的所有訂單都在同一個節點,數據相對平均。其他典型分片策略有根據時間來分等等,總之分片是很重要的東西。

修改schema.xml,增加以下配置

 <!-- 這里配置的orders表是進行水平拆分的,orders的數據將會放到dn1和dn2兩個節點上,數據的分配策略是 mod_rule  -->
  <table name="orders" dataNode="dn1,dn2" rule="mod_rule" ></table>

schema.xml全配置文件如下

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <!-- 這里schema配置的意思是 操作customer表的時候 那么就走dn2節點查詢,否則走dn1節點  -->
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
                <table name="customer" dataNode="dn2" ></table>
                 <!-- 這里配置的orders表是進行水平拆分的,orders的數據將會放到dn1和dn2兩個節點上,數據的分配策略是 mod_rule  -->
                <table name="orders" dataNode="dn1,dn2" rule="mod_rule" ></table>
        </schema>
        <dataNode name="dn1" dataHost="host1" database="orders" />
        <dataNode name="dn2" dataHost="host2" database="orders" />

        <dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.107.135:3306" user="mysqlu1" password="12345678">

                </writeHost>
        </dataHost>

        <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM2" url="192.168.107.129:3306" user="mysqlu1" password="12345678">

                </writeHost>
        </dataHost>

</mycat:schema>

修改配置文件rule.xml,在rule配置文件里新增分片規則mod_rule,并指定規則適用字段為customer_id,還要選擇分片算法mod-long(對字段求模運算),customer_id對兩個節點求模,根據結果分片

        <tableRule name="mod_rule">
                <rule>
                        <columns>customer_id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>
  
        <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
            <property name="count">2</property>
        </function>

現在我們在數據節點dn2上建orders表,因為之前只有dn1有orders表。在mycat命令行插入數據(字段不能省略)

-- 這里必須指明字段列(id,order_type,customer_id,amount) 不能省略,否則mycat不能識別
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);

在兩個庫分別查看數據


image.png

image.png

在mycat中查詢數據


image.png

因為數據是從兩個庫中來的,所以順序和我們之前的單庫不一樣,我們制定排序字段就可以了。到此分表已經成功。
mycat join查詢

上面的orders表已經分開了,那么與其相關的orders_detail表怎么辦呢?假設我們現在執行一條關聯sql(如下)。那會不會有問題?答案是肯定有問題,mycat經過分片分析在dn1和dn2節點都進行join查詢。因為其中一個節點沒有orders_detail 表,所以必然報錯,最終結果也就是報錯。

SELECT  * FROM orders t1 LEFT JOIN orders_detail t2 WHERE  t1.id = t2.order_id

mycat 解決上面問題的方法是 使用ER表。Mycat 借鑒了 NewSQL 領域的新秀 Foundation DB 的設計思路,Foundation DB 創新性的提出了 Table Group 的概念,其將子表的存儲位置依賴于主表,并且物理上緊鄰存放,因此徹底解決了JION 的效率和性能問 題,根據這一思路,提出了基于 E-R 關系的數據分片策略,子表的記錄與所關聯的父表記錄存放在同一個數據分片上。
更改schema.xml配置文件 將orders_detail的主表設置為orders,根據orders的id與orders_detail的id的關系來分配。

                <table name="orders" dataNode="dn1,dn2" rule="mod_rule" >
                        <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />
                </table>

在dn2上新建orders_detail表,然后在mycat上插入數據

INSERT INTO orders_detail(id,detail,order_id) values(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

在mycat、dn1、dn2中運行兩個表join語句,能看到對應的結果,其中mycat的結果是結果總集,是各個節點的數據總和。

Select o.*,od.detail from orders o inner join orders_detail od on o.id=od.order_id;

mycat 全局表

在分片的情況下,當業務表因為規模而進行分片以后,業務表與這些附屬的字典表之間的關聯,就成了比較 棘手的問題,考慮到字典表具有以下幾個特性:
① 變動不頻繁
② 數據量總體變化不大
③ 數據規模不大,很少有超過數十萬條記錄
鑒于此,Mycat 定義了一種特殊的表,稱之為“全局表”,全局表具有以下特性:
① 全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的數據一致性
② 全局表的查詢操作,只從一個節點獲取
③ 全局表可以跟任何一個表進行 JOIN 操作
修改 schema.xml

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

在 dn2 創建 dict_order_type 表。 在Mycat、dn1、dn2中查詢表數據

常用的分片規則

1 取模:此規則為對分片字段求摸運算。也是水平分表最常用規則。
2 分片枚舉
通過在配置文件中配置可能的枚舉 id,自己配置分片,本規則適用于特定的場景,比如有些業務
需要按照省份或區縣來做保存,而全國省份區縣固定的,這類業務使用本條規則。
修改schema.xml配置文件

<table name="orders_ware_info" dataNode="dn1,dn2" rule="sharding_by_intfile" ></table>

修改rule.xml配置文件

        <tableRule name="sharding_by_intfile">
                <rule>
                         <columns>areacode</columns>
                        <algorithm>hash-int</algorithm>
                </rule>
        </tableRule>

    <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
        <property name="mapFile">partition-hash-int.txt</property>
        <property name="type">1</property>
        <property name="defaultNode">0</property>
    </function>

mapFile 表示 算法對應文件
type 表示文件數據類型,0表示整數類型,其他表示String
defaultNode表示 默認節點:小于 0 表示不設置默認節點,大于等于 0 表示設置默認節點,設置默認節點如果碰到不識別的枚舉值,就讓它路由到默認節點,如不設置不識別就報錯
修改partition-hash-int.txt配置文件

110=0
120=1

在mycat上建表,并且插入數據


CREATE TABLE orders_ware_info
(
 `id` INT AUTO_INCREMENT comment '編號',
 `order_id` INT comment '訂單編號',
 `address` VARCHAR(200) comment '地址',
`areacode` VARCHAR(20) comment '區域編號',
PRIMARY KEY(id)
);

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');
INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (3,2,'上海','130');

在Mycat、dn1、dn2可以看到數據分片效果
3 范圍約定
此分片適用于,提前規劃好分片字段某個范圍屬于哪個分片。
修改schema.xml配置文件

<table name="payment_info" dataNode="dn1,dn2" rule="auto_sharding_long" ></table>

修改rule.xml配置文件

<tableRule name="auto_sharding_long">
     <rule>
         <columns>order_id</columns>
         <algorithm>rang-long</algorithm>
     </rule>
</tableRule>

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txt</property>
    <property name="defaultNode">0</property>
</function>

修改autopartition-long.txt配置文件,以order_id區分,0-100的數據放0節點,101-200放1節點

0-100=0
101-200=1

mycat下,建表 插入數據 驗證即可

CREATE TABLE payment_info
(
 `id` INT AUTO_INCREMENT comment '編號',
 `order_id` INT comment '訂單編號',
 `payment_status` INT comment '支付狀態',
 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);

4 按日期分片
此規則為按天分片。設定時間格式、范圍
修改schema.xml配置文件

<table name="login_info" dataNode="dn1,dn2" rule="sharding_by_date" ></table>

修改rule.xml配置文件

<tableRule name="sharding_by_date">
     <rule>
         <columns>login_date</columns>
         <algorithm>shardingByDate</algorithm>
     </rule>
</tableRule>

<function name="shardingByDate" class="io.mycat.route.function.PartitionByDate">
     <property name="dateFormat">yyyy-MM-dd</property>
     <property name="sBeginDate">2019-01-01</property>
     <property name="sEndDate">2019-01-04</property>
     <property name="sPartionDay">2</property> 
</function>

columns:分片字段,algorithm:分片函數
dateFormat :日期格式
sBeginDate :開始日期
sEndDate:結束日期,則代表數據達到了這個日期的分片后循環從開始分片插入
sPartionDay :分區天數,即默認從開始日期算起,分隔 2 天一個分區

重啟mycat 建表 加數據 ,驗證

CREATE TABLE login_info
(
 `id` INT AUTO_INCREMENT comment '編號',
 `user_id` INT comment '用戶編號',
 `login_date` date comment '登錄日期',
 PRIMARY KEY(id)
); 

INSERT INTO login_info(id,user_id,login_date) VALUES (1,101,'2019-01-01');
INSERT INTO login_info(id,user_id,login_date) VALUES (2,102,'2019-01-02');
INSERT INTO login_info(id,user_id,login_date) VALUES (3,103,'2019-01-03');
INSERT INTO login_info(id,user_id,login_date) VALUES (4,104,'2019-01-04');
INSERT INTO login_info(id,user_id,login_date) VALUES (5,103,'2019-01-05');
INSERT INTO login_info(id,user_id,login_date) VALUES (6,104,'2019-01-06');

5 全局序列
在實現分庫分表的情況下,數據庫自增主鍵已無法保證自增主鍵的全局唯一。為此,Mycat 提供了全局 sequence,并且提供了包含本地配置和數據庫配置等多種實現方式

  • 方式1 本地文件
    此方式 Mycat 將 sequence 配置到文件中,當使用到 sequence 中的配置后,Mycat 會更下classpath 中的 sequence_conf.properties 文件中 sequence 當前的值。
    ① 優點:本地加載,讀取速度較快
    ② 缺點:抗風險能力差,Mycat 所在主機宕機后,無法讀取本地文件。
  • 方式2 數據庫方式
    利用數據庫一個表 來進行計數累加。但是并不是每次生成序列都讀寫數據庫,這樣效率太低。Mycat 會預加載一部分號段到 Mycat 的內存中,這樣大部分讀寫序列都是在內存中完成的。如果內存中的號段用完了 Mycat 會再向數據庫要一次。
  • 方式3 時間戳方式
    全局序列ID= 64 位二進制 (42(毫秒)+5(機器 ID)+5(業務編碼)+12(重復累加) 換算成十進制為 18 位數的long 類型,每毫秒可以并發 12 位二進制的累加。
    ① 優點:配置簡單
    ② 缺點:18 位 ID 過長
  • 方式4 自主生成全局序列 推薦這種方式比較好
    ① 根據業務邏輯組合
    ② 可以利用 redis 的單線程原子性 incr 來生成序列。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379