利用Mycat中间件实现RDS MySQL的分库分表及读写分离功能
https://aws.amazon.com/cn/blogs/china/mycat-rds-mysql/
隨著移動互聯網的興起和大數據的蓬勃發展,系統的數據量正呈幾何倍數增長,系統的壓力也越來越大,這時最容易出現的問題就是服務器繁忙,我們可以通過增加服務器及改造系統來緩解壓力,然后采用負載均衡、動靜分離、緩存系統來提高系統的吞吐量。然而,當數據量的增長達到一定程度的時候,增加應用服務器并不能明顯地提高系統的效率,因為所有壓力都會傳導到數據庫層面,而大多數系統都是用一個數據庫來存儲和管理系統數據的,因而一個支持高性能、高并發并且易于擴展的數據庫系統變的尤為重要。
Amazon RDS是AWS上托管的關系型數據庫服務,目前支持業界主流的MySQL、Oracle、SQL Server、PostgreSQL、MariaDB引擎及AWS提供的Aurora,通過多可用區主備及讀副本等技術,能夠支持絕大部分的應用場景。
對于更大容量的數據庫,可以使用Amazon Aurora,Aurora是一個關系型數據庫引擎,結合了高端商用數據庫的速度和可用性,同時還具有開源數據庫的簡單性和成本效益。Amazon Aurora 的設計與 MySQL 5.6 及PostgreSQL 9.6.1兼容,它提供的性能比同一硬件上運行的標準 MySQL 最多高達五倍,比PostgreSQL最多高達二倍。
下表是單個數據庫實例能夠支持的存儲容量大小:
| RDS數據庫引擎 | 存儲容量 |
| MySQL | 6TB |
| Oracle | 6TB |
| PostgreSQL | 6TB |
| MariaDB | 6TB |
| SQL Server | 4TB |
| Aurora | 64TB |
不過由于Aurora目前并未在所有region提供,比如中國北京,同時支持的引擎有限,對于中國區用戶及使用其他數據庫引擎的用戶,不得不考慮其他的解決方案。隨著近年來海量數據存儲、并行計算、異構數據互聯等一系列新技術在市場上不斷出現。相信數據庫行業的很多從業者都對傳統關系型數據庫的單點故障及容量問題頭疼不已,而數據庫分庫分表也早已成為解決此類問題的基礎。
本文要介紹的Mycat是一款面向企業級應用的開源數據庫中間件產品,支持事務、ACID,能夠對接Oracle、MySQL、DB2、SQL Server、MongoDB、SequoiaDB等數據庫,支持透明的讀寫分離機制,支持各種MySQL集群,包括標準的主從異步集群、MySQL Galera Cluster多主同步集群等,通過大表水平分片方式支持100億級大表的分布式存儲和秒級的并行查詢能力,內建數據庫集群故障切換機制,實現自動切換,可滿足大部分應用的高可用性要求。
配置步驟:
第一步 創建RDS數據庫實例
創建一個RDS將會使用的參數組mycat
在分庫分表的情況下,Mycat可以通過如下幾種方式保證自增主鍵的全局唯 一:
1. 本地文件方式
在sequence_conf.properties文件中設置主鍵的當前值,最小值和最大值
2. 數據庫方式
在其中一個 MySQL 節點中建立一張表,存放 sequence 的名稱,當前值,步長 等信息,并通過存儲過程修改更新信息
3. 本地時間戳方式
4. 注解方式
本例使用第二種方式,為了使存儲過程能夠順利執行,需要修改參數組的log_bin_trust_function_creators為1
此外,可以按需設置時區及大小寫不敏感
接著創建兩臺 RDS MySQL 實例,注意需要在創建的時候選擇 mycat 參數組
本例使用 MySQL 5.6.34 版本,開啟 Multi-AZ 及自動備份功能,并且為每個 MySQL RDS實例創建一個讀副本做讀寫分離
數據庫 endpoint 如下:
mysql1
mysql1.cbqbpwftrsrj.rds.cn-north-1.amazonaws.com.cn
mysql1-read-replica
mysql1-read-replica.cbqbpwftrsrj.rds.cn-north-1.amazonaws.com.cn
mysql2
mysql2.cbqbpwftrsrj.rds.cn-north-1.amazonaws.com.cn
mysql2-read-replica
mysql2-read-replica.cbqbpwftrsrj.rds.cn-north-1.amazonaws.com.cn
第二步 安裝配置 Mycat
本例使用 Cento 6.7 創建 EC2
1. 安裝epel及mysql源
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh https://repo.mysql.com//mysql57-community-release-el6-9.noarch.rpm
2. 修改/etc/yum.repos.d/mysql-community.repo如下
3. 安裝相關軟件包
yum update -y
yum install mysql-server java-1.8.0-openjdk.x86_64 vim wget -y
4. 下載并安裝Mycat
wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
tar xzvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
5. 配置Mycat中間件
5.1 vim mycat/conf/server.xml
該配置文件主要用于創建 mycat 用戶及 mycat 的系統參數設置,這里只列出保證mycat正常工作的參數配置,其中還有很多優化項需要讀者根據需要自行修改,具體可以參考文末的參考書及鏈接
其中 sequenceHandlerType 為1表示使用數據庫方式實現自增主鍵
5.2 vim mycat/conf/schema.xml
該配置文件主要用于配置邏輯庫、表、分配規則、分配節點及數據源,同樣這里的配置并不包括參數優化在內
上面配置有幾個地方需要注意
1. 分片dn1和dn2分別對應于mysql1中的db1和mysql2中的db2,需要事先登入這兩臺 RDS 實例,并分別創建 db1 和 db2 數據庫
2. user表會在兩臺RDS實例中分片,基于id字段,使用mod-long算法進行分片
3. orders 表作為 user 表的子表,使用 ER 關系表進行分片,是 Mycat 中避免跨庫join 的其中一種方式,適用于有父子關系的兩張表,這里 orders 表中的user_id 字段對應于 user 表中的 id 字段,當需要對 orders 表進行插入操作的時候,Mycat 會對 user_id 應用父表的 mod-long 算法找到具體的分片并插入,這樣 order 表和user 表基于user.id=orders.user_id 的 join 操作可以在每個分片中進行,無需跨庫
4. country表的type為global,設置為全局表,也就是在每個RDS實例中均有完整的 country 表信息,是 Mycat 中另外一種避免跨庫 join 的方法,適用于內容較為固定,數據量不大的字典表
5. dataHost標簽中的balance為3,實現讀請求完全到readHost上進行
6. dataHost標簽中的switchType為-1,意思是當writeHost故障的時候不進行切換,這是針對 RDS 特有的配置,由于 RDS 已經啟用了 Multi-AZ 的功能,主庫故障會自動切換到 standby 實例,無需 Mycat 切換到某臺readHost
7. user,password為具體RDS實例的登入用戶賬號
8. user表和orders表設置了autoIncrement=true主鍵自增
9. mycat_sequence表用于存儲其他表的自增主鍵信息
5.3 vim mycat/conf/rule.xml
該配置文件主要用于定義分片算法,由于本例使用兩臺 RDS實例,需要將 mod-long 分片算法的 data nodes 參數設成 2
5.4 vim mycat/conf/sequence_db_conf.properties
該配置文件用于設置主鍵自增表的自增信息,這里將 user 表和 orders 表的自增信息存到 dn1,也就是 RDS mysql1 中,注意這里的 USER,ORDERS 需要大寫
5.5 啟動 Mycat,并建表
./mycat/bin/mycat start &
mysql –h 127.0.0.1 –u root –p –P 8066
show databases 可以看到定義的邏輯庫 test
下面是具體的建表語句
下面設置 user 表及 orders 表的自增主鍵的當前值為0,自增步長為1
5.6 配置實現主鍵自增的存儲過程
存儲過程需要在具體的 RDS 實例上創建,在這里是 RDS mysql1
mysql –h mysql1.cbqbpwftrsrj.rds.cn-north-1.amazonaws.com.cn -u root –p
第三步 功能驗證
1. 登入Mycat
mysql –h 127.0.0.1 –u root –p –P 8066 use test;
2. 驗證主鍵自增
3. 驗證user表在兩臺RDS實例中分片
4. 驗證country表為全局表,并且能夠和user表做join
在兩臺 RDS 實例上可以看到 country 表的全部內容
5. 驗證 orders 表的分片規則關聯父表 user 表,即 orders 表中的 user_id 與 user 表中 id字段相等的行存儲在同一個 RDS 實例中,并且兩張表能夠 join
在兩臺 RDS 上查看到 user 表與 orders 表的存儲關系
6. 驗證使用ShareJoin實現分片join
如上兩種方式本質上是通過全局表或者相同的分片規則規避分片 join,SQL語句經過 Mycat 分發到各個 RDS 節點本地 join,然后在Mycat 中進行結果的匯聚,如果兩張表都比較大,不適合作為全局表并且表與表之間沒有類似的父子關系時,有兩種方式解決
1. 增加冗余列,即人為在兩張表中構建相同的兩列,比如上例的 user.id 和orders.user_id,然后基于這兩列來分片
2. 通過ShareJoin注解,ShareJoin本質上是將一條join語句拆分成單表的SQL語句,然后把各個節點的數據匯集
登入 RDS mysql1,對 orders 表人為插入一條 user_id 為奇數的信息,使得 orders 表的分片規則與 user 表的出現
此時再使用 join 語句將會丟失剛剛插入的那一行,因為 RDS mysql1 在本地執行 join 語句時,本地 user 表中并沒有 user.id=1 的條目
通過在 SQL 語句前加上 ShareJoin 的注解,實現跨分片 join 功能
筆者在實際使用過程中發現,ShareJoin 并不是總能夠正常工作,懷疑可能是 bug 或者語句限制,不到萬不得已,建議使用上面的兩種方式來規避跨庫 join,比如上面的語句如果只是取出某幾列,ShareJoin 并不總能正確輸出
另外還有一種 Mycat 支持的跨分片join技術是 catlet,也叫做人工智能(HBT), 主要是參考了數據庫中的存儲過程的實現方式,需要用戶根據系統提供的 API 接口在代碼中實現跨分片 join,具體可以參考文末的參考書中的內容
7. 驗證讀寫分離
修改 RDS 參數組 mycat,開啟 general log
注意:開啟 general log 會影響數據庫的性能并占用存儲空間,不建議在常規時間開啟,這里只是用于驗證
登入 Mycat,執行如下語句,可以看到在15:42:09-15:42:29的時間段內,一共執行了兩次對 country 表的全表掃描,一次 user 表的全表掃描,和三次 user 表的單行查詢,需要驗證的結果如下:
1. 由于country表是全局表,只會在一臺實例上執行,所以兩臺read-replica中一共可以看到兩條語句
2. user表是分片表,所以全表掃描會在每臺read-replica中看到一條語句
3. user表的單行掃描會按照Mycat的分片規則分配到相應的read-replica中執行
4. 所有語句不會出現在mysql1和mysql2寫庫的日志中
分別登入 mysql1,mysql2,mysql1-read-replica,mysql2-readreplica 執行 select * from mysql.general_log,查看 15:42:09-15:42:29 時間段內的日志
mysql1,mysql2 中沒有執行的語句日志
mysql1-read-replica 中,可以看到兩條 country 的全表掃描,一條 user 的全表掃描和user 表 id 為 2 的查詢語句,其中全表掃描的 limit 100 為 Mycat 自動添 加,可以通過配置修改
mysql2-read-replica 中,可以看到一條 user 的全表掃描和 user 表 id 為 1,3 的查詢語句,其中全表掃描的 limit 100 為 Mycat 自動添加,可以通過配置修改
第四步 配置 Mycat 的冗余
1. 設置Mycat開機自啟動
vim /etc/rc.local,添加如下啟動指令
sh /home/centos/mycat/bin/mycat start
2. 根據需要設置iptables防火墻策略
3. 創建 AMI,通過 AWS autoscaling-group,實現 Mycat 冗余及高可用,應用層對兩臺MyCat的負載均衡可以在應用層實現或者使用負載均衡器,由于這部分配置比較基礎,此處不做詳細介紹
最終拓撲圖如下:
第五步 使用 Mycat-web 實現監控(可選)
Mycat-web為 Mycat 提供了一個基于 Web 的監控平臺,功能非常豐富,可以對 Mycat實例,Mycat 所在機器的 JVM 以及具體的 MySQL 節點進行監控
1. 安裝啟動Mycat-web
本例使用一臺獨立的 EC2 安裝,使用 Centos 6.7,配置 internet 可以訪問
Mycat-web 依賴 zookeeper,需要先安裝 zookeeper
wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper- 3.4.9.tar.gz
cd zookeeper-3.4.9/conf
mv zoo_sample.cfg zoo.cfg
cd ../bin
./zkServer.sh start &
安裝 Mycat-web
wget http://dl.mycat.io/mycat-web-1.0/Mycat-web-1.0-SNAPSHOT- 20170102153329-linux.tar.gz
cd ~/mycat-web/WEB-INF/classes
vim mycat.properties
zookeeper=localhost:2181(默認已經修改)
cd ~/mycat-web
./start.sh &
2. 配置Mycat-web
通過瀏覽器訪問 mycat-web
添加 Mycat 節點
添加 JVM 節點
添加 MySQL 節點
接下來就可以通過 Mycat-web 查看系統的各項參數
目前有一個問題,Mycat-web 只能夠收集到 read 的操作,所有 insert/delete/update 等寫操作無法收集
通過 Mycat 服務端口 8066 登入一臺 Mycat,執行一系列 select 及 insert 讀寫操作,退出后通過管理端口 9066 登入,查看日志發現所有 insert 寫操作并未記錄到日志中,因此可以確定不是 Mycat-web 的問題,而是可能由于 Mycat 本身配置不當或者由于 bug 導致寫操作沒有記錄到日志中,已經在 github 上提交 issue,等待答復中
參考內容:
《分布式數據庫架構及企業實踐:基于Mycat中間件》
Mycat 自增主鍵配置:
http://deweing.github.io/2016/06/29/mycat-auto-increment.html
https://my.oschina.net/bodi666/blog/797277
轉載于:https://www.cnblogs.com/davidwang456/articles/8995158.html
總結
以上是生活随笔為你收集整理的利用Mycat中间件实现RDS MySQL的分库分表及读写分离功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 水平分库分表的关键步骤以及可能遇到的问题
- 下一篇: Mybatis实现分库分表