MySQL搭建主从复制 读写分离 分库分表 MyCat高可用
主從演示
讀寫演示?
?
分表演示
主從復制
環境的介紹?
系統環境:centos7.0 客戶端連接工具:xshell 遠程文件傳輸工具:xftp 服務器: 192.168.126.138(主) 192.168.126.139(從)基于rpm實現MySQL的安裝
#查看有沒有安裝MySQL rpm -qa | grep -i mysql #卸載 rpm -e --nodeps mysql-community-client-5.7.28-1.el7.x86_64 #查找 find / -name mysql #刪除存在的MySQL文件 rm -rf /etc/selinux/targeted/active/modules/100/mysql /usr/lib64/mysql /usr/share/mysql #安裝server rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm --force --nodeps #安裝客戶端 rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm --force --nodeps登錄MySQL
[root@localhost home]# mysql -u root -p Enter password: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) #出現錯誤(因為密碼不正確) #實現免密登錄 #修改配置文件 vi /etc/my.cnf #在MySQLd的下面加上 跳過授權 skip-grant-tables #重啟MySQL的服務 service mysqld restart #繼續登錄 mysql -u root -p Enter password:(這個地方不用輸入任何東西直接回車) #其實免密登錄時不安全的,所以進來之后一定要設置密碼 #刷新系統權限表 flush PRIVILEGES; #重新設置密碼 #alter user 'root'@'localhost' identified by '123456'; SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456'); #刷新系統權限表 flush PRIVILEGES; #記得添加一個數據庫 mysql> create database youruike; Query OK, 1 row affected (0.00 sec)mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | youruike | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) #退出MySQL mysql> exit;實現MySQL的主從復制
#先配置主服務器 #修改配置文件 粘貼在放在[mysqld]下面的 vi /etc/my.cnf #添加以下的內容 #日志文件的名字 log_bin=master-a-bin #日志文件的格式 binlog-format=ROW #服務器的id(zk的集群),一定要是唯一的 server-id=1 #對應需要實現主從復制的數據庫 binlog_do_db=youruike#添加完之后需要登錄主服務器給從服務器授權 就是允許從服務器讀取主服務器數據庫 grant replication slave on *.* to 'root'@'192.168.126.%' identified by '123456'; #刷新系統權限表 flush PRIVILEGES;從服務器的配置
#修改配置文件 vi /etc/my.cnf #添加以下的內容 #日志文件的名字 log_bin=master-a-bin #日志文件的格式 binlog-format=ROW #服務器的id(zk的集群),一定要是唯一的 server-id=2 #雙主互相備份(表示從服務器可能是另外一臺服務器的主服務器) #log-slave-updates=true設置并驗證主從復制
#重啟主服務器和從服務器 service mysqld restart #登錄主服務器 mysql -u root -p #查看主服務器的狀態 mysql> show master status; +---------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------------+----------+--------------+------------------+-------------------+ | master-a-bin.000001 | 154 | youruike | | | +---------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.01 sec) #解釋對應的一些名詞 #File 生成的日志文件名 #Position 文件名所處的一個位置(偏移量) #Binlog_Do_DB需要實現主從復制的數據庫 #啟動服務 systemctl mysqld restart#登錄從服務器 #設置從服務器如何找到主服務器 #設置主從復制的日志和偏移量 change master to master_host='192.168.126.165',master_port=3306,master_user='root',master_password='123456',master_log_file='master-a-bin.000001',master_log_pos=154;#啟動slave的數據同步 start slave; #停止slave的數據同步 stop slave; #查看salve的配置信息 show slave status\G;#這邊還正在連接中 mysql> show slave status\G; *************************** 1. row ***************************Slave_IO_State: Connecting to masterMaster_Host: 192.168.126.138Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-a-bin.000001Read_Master_Log_Pos: 154Relay_Log_File: localhost-relay-bin.000001Relay_Log_Pos: 4Relay_Master_Log_File: master-a-bin.000001Slave_IO_Running: ConnectingSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 154Relay_Log_Space: 154Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 2003Last_IO_Error: error connecting to master 'root@192.168.126.138:3306' - retry-time: 60 retries: 1Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0Master_UUID: Master_Info_File: /var/lib/mysql/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: 191119 20:48:42Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)ERROR: No query specified #需要解決正在連接中的問題 #使用navicat客戶端進行連接,發現連接不上 #1.防火墻的問題 2.端口未開放 3.未授權 #可以開放端口3306 firewall-cmd --zone=public --add-port=3306/tcp --permanent #重新加載防火墻 firewall-cmd --reload #還是沒有將權限授予客戶端 #with grant option 不僅僅是授予增刪改查的權限,還授予權限的權限 grant all privileges on *.* to root@'%' identified by '123456' with grant option; #授權報錯 mysql> grant all privileges on *.* to root@'%' identified by '123456' with grant option; ERROR 1819 (HY000): Unknown error 1819 mysql> select @@validate_password_policy; +----------------------------+ | @@validate_password_policy | +----------------------------+ | MEDIUM | +----------------------------+ 1 row in set (0.00 sec)mysql> SHOW VARIABLES LIKE 'validate_password%'; +--------------------------------------+--------+ | Variable_name | Value | +--------------------------------------+--------+ | validate_password_check_user_name | OFF | | validate_password_dictionary_file | | | validate_password_length | 8 | | validate_password_mixed_case_count | 1 | | validate_password_number_count | 1 | | validate_password_policy | MEDIUM | | validate_password_special_char_count | 1 | +--------------------------------------+--------+ 7 rows in set (0.00 sec)mysql> set global validate_password_policy=0; Query OK, 0 rows affected (0.00 sec)mysql> set global validate_password_mixed_case_count=0; Query OK, 0 rows affected (0.00 sec)mysql> set global validate_password_number_count=3; Query OK, 0 rows affected (0.00 sec)mysql> set global validate_password_special_char_count=0; Query OK, 0 rows affected (0.00 sec)mysql> set global validate_password_length=3; Query OK, 0 rows affected (0.00 sec)mysql> SHOW VARIABLES LIKE 'validate_password%'; +--------------------------------------+-------+ | Variable_name | Value | +--------------------------------------+-------+ | validate_password_check_user_name | OFF | | validate_password_dictionary_file | | | validate_password_length | 3 | | validate_password_mixed_case_count | 0 | | validate_password_number_count | 3 | | validate_password_policy | LOW | | validate_password_special_char_count | 0 | +--------------------------------------+-------+ 7 rows in set (0.00 sec)mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456'); Query OK, 0 rows affected (0.00 sec)mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)mysql> grant all privileges on *.* to root@'%' identified by '123456' with grant option; Query OK, 0 rows affected, 1 warning (0.01 sec)mysql> flush privileges; Query OK, 0 rows affected (0.00 sec)#重啟從服務器并且查看狀態 #表示成功Slave_IO_Running: Yes Slave_SQL_Running: Yes mysql> stop slave; Query OK, 0 rows affected (0.00 sec)mysql> start slave; Query OK, 0 rows affected (0.01 sec)mysql> show slave status\G; *************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 192.168.126.138Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-a-bin.000001Read_Master_Log_Pos: 1000Relay_Log_File: localhost-relay-bin.000003Relay_Log_Pos: 323Relay_Master_Log_File: master-a-bin.000001Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 1000Relay_Log_Space: 1549Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 0f900ff3-0ac6-11ea-aac7-000c299a89e6Master_Info_File: /var/lib/mysql/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)ERROR: No query specified測試是否成功
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | youruike | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec)mysql> use youruike; Database changed mysql> show tables; Empty set (0.00 sec)mysql> create table user(id int primary key auto_increment,name varchar(20) not null)charset='utf8'; Query OK, 0 rows affected (0.12 sec)mysql> show tables; +---------------+ | Tables_in_youruike | +---------------+ | user | +---------------+ 1 row in set (0.00 sec)mysql> insert into user values(null,'a'); Query OK, 1 row affected (0.01 sec)mysql> select * from user; +----+------+ | id | name | +----+------+ | 1 | a | +----+------+ 1 row in set (0.00 sec)mysql> insert into user values(null,'b'); Query OK, 1 row affected (0.01 sec)mysql> insert into user values(null,'c'); Query OK, 1 row affected (0.00 sec)mysql> delete from user where id = 3; Query OK, 1 row affected (0.00 sec)mysql> select * from user; +----+------+ | id | name | +----+------+ | 1 | a | | 2 | b | +----+------+ 2 rows in set (0.00 sec)讀寫分離
要想實現讀寫分離,一定要是基于主從復制而實現的
系統環境
系統環境:centos7.0 mycat的版本:1.6 MySQL主機:192.168.126.143(mycat也使用這臺主機) MySQL從機:192.168.126.148 mycat的下載地址:http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz安裝mycat
#查詢有沒有安裝mycat find / -name mycat #因為mycat是基于java語言編寫的,所以一定要配置jdk的環境 #解壓jdk tar -zxvf jdk-8u221-linux-x64.tar.gz #配置環境變量 [root@localhost home]# ls ange jdk1.8.0_221 jdk-8u221-linux-x64.tar.gz [root@localhost home]# mv jdk1.8.0_221/ jdk8 [root@localhost home]# mv jdk8 /usr/ [root@localhost home]# ls ange jdk-8u221-linux-x64.tar.gz [root@localhost home]# cd /usr/ [root@localhost usr]# ls bin etc games include jdk8 lib lib64 libexec local sbin share src tmp [root@localhost usr]# vi /etc/profile #加到最末尾 JAVA_HOME=/usr/jdk8 CLASSPATH=%JAVA_HOME%/lib:%JAVA_HOME%/jre/lib PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin export PATH CLASSPATH JAVA_HOME [root@localhost usr]# source /etc/profile [root@localhost usr]# java -version java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode) [root@localhost usr]# #安裝mycat #報錯 [root@localhost usr]# wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz-bash: wget: 未找到命令 #安裝wget yum install wget #繼續執行下載命令 wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz #加壓下載好的壓縮文件 tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz #mycat的目錄結構 -lib jar包存放的目錄 -conf-schema.xml-server.xml-rule.xml-log4j2.xml -logs-mycat.log-wrapper.log -bin-mycat.shlib jar包 schema.xml主配置文件 server.xml服務配置文件 rule.xml分片的配置文件 log.xml日志配置文件 mycat.log啟動日志文件 wrapper.log運行配置日志文件 mycat.sh啟動的命令配置mycat
先配置server.xml
<!-- 有讀寫權限的用戶(最高權限的用戶) --> <user name="root"><property name="password">123456</property><!-- 對應schema.xml的邏輯數據庫名稱 --><property name="schemas">TESTDB</property> </user><!-- 只有只讀權限 --> <user name="user"><property name="password">123456</property><property name="schemas">TESTDB</property><property name="readOnly">true</property> </user>schema.xml
<?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"><!-- 里面的tables是實現分庫分表的 --></schema><dataNode name="dn1" dataHost="localhost1" database="youruike" /><!--1. balance="0",所有讀操作都發送到當前可用的writeHost上。2. balance="1",所有讀操作都隨機的發送到readHost。3. balance="2",所有讀操作都隨機的在writeHost、readhost上分發。4. balance="3",所有讀請求隨機的分發到 wiriterHost 對應的 readhost 執行,writerHost 不負擔讀壓力,注意 balance=3 只在 1.4 及其以后版本有,1.3沒有1. writeType="0", 所有寫操作都發送到可用的writeHost上。2. writeType="1",所有寫操作都隨機的發送到readHost。3. writeType="2",所有寫操作都隨機的在writeHost、readhost分上發--><dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><!-- 心跳檢測,檢測主機和從機是否正常 --><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="127.0.0.1:3306" user="root"password="123456"><readHost host="hostS2" url="192.168.126.148:3306" user="root" password="123456" /></writeHost></dataHost> </mycat:schema>啟動mycat
[root@localhost bin]# ./mycat start console Starting Mycat-server... [root@localhost bin]# ./mycat status console Mycat-server is running (11067). [root@localhost bin]# netstat -ntlp -bash: netstat: 未找到命令 [root@localhost bin]# yum -y install net-tools [root@localhost bin]# netstat -ntlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 11069/java tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1030/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1188/master tcp6 0 0 :::1984 :::* LISTEN 11069/java tcp6 0 0 :::8066 :::* LISTEN 11069/java tcp6 0 0 :::9066 :::* LISTEN 11069/java tcp6 0 0 :::3306 :::* LISTEN 1742/mysqld tcp6 0 0 :::39666 :::* LISTEN 11069/java tcp6 0 0 :::22 :::* LISTEN 1030/sshd tcp6 0 0 :::41304 :::* LISTEN 11069/java tcp6 0 0 ::1:25 :::* LISTEN 1188/master登錄mycat查看配置內容
#登錄mycat的管理端口 mysql -uroot -p123456 -h127.0.0.1 -P9066 #查看幫助手冊 show @@help; #查看讀寫分離情況 show @@datasource; #查看心跳檢測 show @@heartbeat;RS_CODE 狀態:OK_STATUS = 1;正常狀態ERROR_STATUS = -1; 連接出錯TIMEOUT_STATUS = -2; 連接超時INIT_STATUS = 0; 初始化狀態 #連接數據端口(登錄mycat的主機,mycat在192.168.126.161) mysql -uroot -p123456 -h127.0.0.1 -P8066測試讀寫分離情況
#修改日志打印情況 <Loggers><!--<AsyncLogger name="io.mycat" level="info" includeLocation="true" additivity="false">--><!--<AppenderRef ref="Console"/>--><!--<AppenderRef ref="RollingFile"/>--><!--</AsyncLogger>--><asyncRoot level="debug" includeLocation="true"><AppenderRef ref="Console" /><AppenderRef ref="RollingFile"/></asyncRoot> </Loggers>#查看日志情況 tail -f wrapper.log分庫分表
為什么要分庫分表(設計高并發系統的時候,數據庫層面該如何設計)?用過哪些分庫分表中間件?不同的分庫分表中間件都有什么優點和缺點?你們具體是如何對數據庫如何進行垂直拆分或水平拆分的?
為什么要分庫分表?(設計高并發系統的時候,數據庫層面該如何設計?)
說白了,分庫分表是兩回事兒,大家可別搞混了,可能是光分庫不分表,也可能是光分表不分庫,都有可能。給大家拋出來一個場景。
假如我們現在是一個小創業公司(或者是一個 BAT 公司剛興起的一個新部門),現在注冊用戶就 20 萬,每天活躍用戶就 1 萬,每天單表數據量就 1000,然后高峰期每秒鐘并發請求最多就 10。天,就這種系統,隨便找一個有幾年工作經驗的,然后帶幾個剛培訓出來的,隨便干干都可以。
結果沒想到我們運氣居然這么好,碰上個 CEO 帶著我們走上了康莊大道,業務發展迅猛,過了幾個月,注冊用戶數達到了 2000 萬!每天活躍用戶數 100 萬!每天單表數據量 10 萬條!高峰期每秒最大請求達到 1000!同時公司還順帶著融資了兩輪,進賬了幾個億人民幣啊!公司估值達到了驚人的幾億美金!這是小獨角獸的節奏!
好吧,沒事,現在大家感覺壓力已經有點大了,為啥呢?因為每天多 10 萬條數據,一個月就多 300 萬條數據,現在咱們單表已經幾百萬數據了,馬上就破千萬了。但是勉強還能撐著。高峰期請求現在是 1000,咱們線上部署了幾臺機器,負載均衡搞了一下,數據庫撐 1000QPS 也還湊合。但是大家現在開始感覺有點擔心了,接下來咋整呢……
再接下來幾個月,我的天,CEO 太牛逼了,公司用戶數已經達到 1 億,公司繼續融資幾十億人民幣啊!公司估值達到了驚人的幾十億美金,成為了國內今年最牛逼的明星創業公司!天,我們太幸運了。
但是我們同時也是不幸的,因為此時每天活躍用戶數上千萬,每天單表新增數據多達 50 萬,目前一個表總數據量都已經達到了兩三千萬了!扛不住啊!數據庫磁盤容量不斷消耗掉!高峰期并發達到驚人的 5000~8000 !別開玩笑了,哥。我跟你保證,你的系統支撐不到現在,已經掛掉了!
好吧,所以你看到這里差不多就理解分庫分表是怎么回事兒了,實際上這是跟著你的公司業務發展走的,你公司業務發展越好,用戶就越多,數據量越大,請求量越大,那你單個數據庫一定扛不住。
分表
比如你單表都幾千萬數據了,你確定你能扛住么?絕對不行,單表數據量太大,會極大影響你的 sql 執行的性能,到了后面你的 sql 可能就跑的很慢了。一般來說,就以我的經驗來看,單表到幾百萬的時候,性能就會相對差一些了,你就得分表了。
分表是啥意思?就是把一個表的數據放到多個表中,然后查詢的時候你就查一個表。比如按照用戶 id 來分表,將一個用戶的數據就放在一個表中。然后操作的時候你對一個用戶就操作那個表就好了。這樣可以控制每個表的數據量在可控的范圍內,比如每個表就固定在 200 萬以內。
分庫
分庫是啥意思?就是你一個庫一般我們經驗而言,最多支撐到并發 2000,一定要擴容了,而且一個健康的單庫并發值你最好保持在每秒 1000 左右,不要太大。那么你可以將一個庫的數據拆分到多個庫中,訪問的時候就訪問一個庫好了。
分庫是啥意思?就是你一個庫一般我們經驗而言,最多支撐到并發 2000,一定要擴容了,而且一個健康的單庫并發值你最好保持在每秒 1000 左右,不要太大。那么你可以將一個庫的數據拆分到多個庫中,訪問的時候就訪問一個庫好了。
| 并發支撐情況 | MySQL 單機部署,扛不住高并 | MySQL從單機到多機,能承受的并發增加了多倍 | |
| 發 | |||
| 磁盤使用情況 | MySQL 單機磁盤容量幾乎撐滿 | 拆分為多個庫,數據庫服務器磁盤使用率大大降低 | |
| SQL 執行性能 | 單表數據量太大,SQL 越跑越慢 | 單表數據量減少,SQL 執行效率明顯提升 | |
如何對數據庫如何進行垂直拆分或水平拆分的?
水平拆分的意思,就是把一個表的數據給弄到多個庫的多個表里去,但是每個庫的表結構都一樣,只不過每個庫表放的數據是不同的,所有庫表的數據加起來就是全部數據。水平拆分的意義,就是將數據均勻放更多的庫里,然后用多個庫來扛更高的并發,還有就是用多個庫的存儲容量來進行擴容。
垂直拆分的意思,就是把一個有很多字段的表給拆分成多個表,或者是多個庫上去。每個庫表的結構都不一樣,每個庫表都包含部分字段。一般來說,會將較少的訪問頻率很高的字段放到一個表里去,然后將較多的訪問頻率很低的字段放到另外一個表里去。因為數據庫是有緩存的,你訪問頻率高的行字段越少,就可以在緩存里緩存更多的行,性能就越好。這個一般在表層面做的較多一些。
這個其實挺常見的,不一定我說,大家很多同學可能自己都做過,把一個大表拆開,訂單表、訂單支付表、訂單商品表。
還有表層面的拆分,就是分表,將一個表變成 N 個表,就是讓每個表的數據量控制在一定范圍內,保證 SQL 的性能。否則單表數據量越大,SQL 性能就越差。一般是 200 萬行左右,不要太多,但是也得看具體你怎么操作,也可能是 500 萬,或者是 100 萬。你的SQL越復雜,就最好讓單表行數越少。
好了,無論分庫還是分表,上面說的那些數據庫中間件都是可以支持的。就是基本上那些中間件可以做到你分庫分表之后,中間件可以根據你指定的某個字段值,比如說 userid,自動路由到對應的庫上去,然后再自動路由到對應的表里去。
你就得考慮一下,你的項目里該如何分庫分表?一般來說,垂直拆分,你可以在表層面來做,對一些字段特別多的表做一下拆分;水平拆分,你可以說是并發承載不了,或者是數據量太大,容量承載不了,你給拆了,按什么字段來拆,你自己想好;分表,你考慮一下,你如果哪怕是拆到每個庫里去,并發和容量都ok了,但是每個庫的表還是太大了,那么你就分表,將這個表分開,保證每個表的數據量并不是很大。
而且這兒還有兩種分庫分表的方式:
- 一種是按照 range 來分,就是每個庫一段連續的數據,這個一般是按比如時間范圍來的,但是這種一般較少用,因為很容易產生熱點問題,大量的流量都打在最新的數據上了。
- 或者是按照某個字段 hash 一下均勻分散,這個較為常用。
range 來分,好處在于說,擴容的時候很簡單,因為你只要預備好,給每個月都準備一個庫就可以了,到了一個新的月份的時候,自然而然,就會寫新的庫了;缺點,但是大部分的請求,都是訪問最新的數據。實際生產用 range,要看場景。
hash 分發,好處在于說,可以平均分配每個庫的數據量和請求壓力;壞處在于說擴容起來比較麻煩,會有一個數據遷移的過程,之前的數據需要重新計算 hash 值重新分配到不同的庫或表。
安裝mycat
#解壓縮 tar xzvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz#需要jdk環境變量?配置mycat server.xml
<property name="sequnceHandlerType">0</property><user name="root"><property name="password">123456</property><property name="schemas">mycat_order</property> </user><user name="user"><property name="password">123456</property><property name="schemas">mycat_order</property><property name="readOnly">true</property> </user>配置 schema.xml
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"><schema name="mycat_order" checkSQLschema="false" sqlMaxLimit="100"><table name="t_order" dataNode="dn1,dn2" rule="mod-long"><childTable name="t_order_detail" primaryKey="od_id" joinKey="order_id"parentKey="order_id" /></table></schema><dataNode name="dn1" dataHost="host1" database="youruike2" /><dataNode name="dn2" dataHost="host2" database="youruike2" /><dataHost name="host1" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="host1" url="127.0.0.1:3306" user="root"password="123456"/></dataHost><dataHost name="host2" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="host2" url="192.168.126.147:3306" user="root"password="123456"/></dataHost> </mycat:schema>創建 youruike2數據庫和數據庫表:t_order、t_order_detail
CREATE TABLE `t_order` (`order_id` BIGINT (20),`user_id` INT (11),`pay_mode` TINYINT (4),`amount` FLOAT,`order_date` datetime,PRIMARY KEY (`order_id`) );CREATE TABLE `t_order_detail` (`od_id` BIGINT (20),`order_id` INT (11),`goods_id` INT (11),`unit_price` FLOAT,`qty` INT (11),PRIMARY KEY (`od_id`) );配置rule.xml
<tableRule name="mod-long"><rule><columns>order_id</columns><algorithm>mod-long</algorithm></rule> </tableRule><function name="mod-long" class="io.mycat.route.function.PartitionByMod"><!-- how many data nodes --><property name="count">2</property> </function>配置sequence_conf.properties
#default global sequence GLOBAL.HISIDS= GLOBAL.MINID=10001 GLOBAL.MAXID=20000 GLOBAL.CURID=10000# self define sequence COMPANY.HISIDS= COMPANY.MINID=1001 COMPANY.MAXID=2000 COMPANY.CURID=1000CUSTOMER.HISIDS= CUSTOMER.MINID=1001 CUSTOMER.MAXID=2000 CUSTOMER.CURID=1000ORDER.HISIDS= ORDER.MINID=1001 ORDER.MAXID=2000 ORDER.CURID=1000ORDERDETAIL.HISIDS= ORDERDETAIL.MINID=1001 ORDERDETAIL.MAXID=2000 ORDERDETAIL.CURID=1000啟動并測試
./mycat start插入測試數據
insert into t_order(order_id,user_id,pay_mode,amount) values(next value for MYCATSEQ_ORDER,101,5,11.1);insert into t_order(order_id,user_id,pay_mode,amount) values(next value for MYCATSEQ_ORDER,102,5,22.2);insert into t_order(order_id,user_id,pay_mode,amount) values(next value for MYCATSEQ_ORDER,103,7,33.3);insert into t_order_detail(od_id,order_id,goods_id,unit_price,qty) values(next value for MYCATSEQ_ORDERDETAIL,1001,55,10,20);insert into t_order_detail(od_id,order_id,goods_id,unit_price,qty) values(next value for MYCATSEQ_ORDERDETAIL,1002,66,14,30);insert into t_order_detail(od_id,order_id,goods_id,unit_price,qty) values(next value for MYCATSEQ_ORDERDETAIL,1003,77,14,60);myCat高可用
我們可以使用 HAProxy + Keepalived 配合兩臺 Mycat 搭起 Mycat 集群,實現高可用性。HAProxy
實現了 MyCat 多節點的集群高可用和負載均衡,而 HAProxy 自身的高可用則可以通過 Keepalived 來
實現。
編號 角色 IP 地址 機器名
1 Mycat1 192.168.140.128 host79.youruike
2 Mycat2 192.168.140.127 host80.youruike
3 HAProxy(master) 192.168.140.126 host81.youruike
4 Keepalived(master) 192.168.140.126 host81.youruike
5 HAProxy(backup) 192.168.140.125 host82.youruike
6 Keepalived(backup) 192.168.140.125 host82.youruike
安裝配置 HAProxy
#1準備好HAProxy安裝包,傳到/opt目錄下 #2解壓到/usr/local/src tar -zxvf haproxy-1.5.14.tar.gz -C /usr/local/src #3進入解壓后的目錄,查看內核版本,進行編譯 cd /usr/local/src/haproxy-1.5.14/ uname -r make TARGET=linux310 PREFIX=/usr/local/haproxy ARCH=x86_64 # TARGET=linux310,內核版本,使用uname -r查看內核,如:3.10.0-514.el7,此時該參數就為linux310; #ARCH=x86_64,系統位數; #PREFIX=/usr/local/haprpxy #/usr/local/haprpxy,為haprpxy安裝路徑。 #4編譯完成后,進行安裝 make install PREFIX=/usr/local/haproxy #5安裝完成后,創建目錄、創建HAProxy配置文件 mkdir -p /usr/data/haproxy/ vi /usr/local/haproxy/haproxy.conf #6向配置文件中插入以下配置信息,并保存Mycat之——高可用負載均衡集群的實現(HAProxy + Keepalived + Mycat)_冰河的專欄-CSDN博客_mycat負載均衡配置
globallog 127.0.0.1 local0maxconn 4096chroot /usr/local/haproxypidfile /usr/data/haproxy/haproxy.piduid 99gid 99daemon#debug#quiet defaultslog globalmode tcpoption abortoncloseoption redispatchretries 3maxconn 2000timeout connect 5000timeout client 50000timeout server 50000 listen proxy_statusbind :48066mode tcpbalance roundrobinserver mycat_1 192.168.126.161:8066 check inter 10sserver mycat_2 192.168.126.171:8066 check inter 10s frontend admin_stats bind :7777mode httpstats enableoption httplogmaxconn 10stats refresh 30sstats uri /adminstats auth admin:123123stats hide-versionstats admin if TRUE啟動驗證
#1啟動HAProxy /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.conf #2查看HAProxy進程 ps -ef|grep haproxy #3打開瀏覽器訪問 http://192.168.126.172:7777/admin #在彈出框輸入用戶名:admin密碼:123123 #如果Mycat主備機均已啟動,則可以看到綠色說明成功 #4驗證負載均衡,通過HAProxy訪問Mycat mysql -uroot -p123456 -h 127.0.0.1 -P 48066配置 Keepalived
#1準備好Keepalived安裝包,傳到/opt目錄下 #2解壓到/usr/local/src tar -zxvf keepalived-1.4.2.tar.gz -C /usr/local/src #3安裝依賴插件 yum install -y gcc openssl-devel popt-devel #3進入解壓后的目錄,進行配置,進行編譯 cd /usr/local/src/keepalived-1.4.2 ./configure --prefix=/usr/local/keepalived #4進行編譯,完成后進行安裝 make && make install #5運行前配置 cp /usr/local/src/keepalived-1.4.2/keepalived/etc/init.d/keepalived /etc/init.d/ mkdir /etc/keepalived cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ cp /usr/local/src/keepalived-1.4.2/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ #6修改配置文件 vi /etc/keepalived/keepalived.conf #修改內容如下 ! Configuration File for keepalived global_defs {notification_email {xlcocoon@foxmail.com}notification_email_from keepalived@showjoy.comsmtp_server 127.0.0.1smtp_connect_timeout 30router_id LVS_DEVELvrrp_skip_check_adv_addrvrrp_garp_interval 0vrrp_gna_interval 0 } vrrp_instance VI_1 {#主機配MASTER,備機配BACKUPstate MASTER#所在機器網卡interface ens33virtual_router_id 51#數值越大優先級越高priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {#虛擬IP192.168.140.200} } virtual_server 192.168.140.200 48066 {delay_loop 6lb_algo rrlb_kind NATpersistence_timeout 50protocol TCPreal_server 192.168.126.172 48066 {weight 1TCP_CHECK {connect_timeout 3retry 3delay_before_retry 3} }real_server 192.168.126.173 48066 {weight 1TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3} } }啟動驗證
#啟動Keepalived service keepalived start #查看啟動情況 ps -ef | grep keepalived #登錄驗證 mysql -uroot -p123456 -h 192.168.140.200 -P 48066測試高可用
#1關閉mycat #2通過虛擬ip查詢數據 mysql -uroot -p123456 -h 192.168.140.200 -P 48066總結
以上是生活随笔為你收集整理的MySQL搭建主从复制 读写分离 分库分表 MyCat高可用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gin新建一个项目的流程与函数
- 下一篇: 违和感(说一说违和感的简介)