上節說到主從複製的一些問題
咱們再來回憶一下
主從複製,增長了一個數據庫副本,從數據庫和主數據庫的數據最終會是一致的
之因此說是最終一致,由於mysql複製是異步的,正常狀況下主從複製數據之間會有一個微小的延遲
經過這個數據庫副本看似解決了數據庫單點問題,但並不完美
由於這種架構下,若是主服務器宕機,須要手動切換從服務器,業務中斷不能忍受,不能知足應用高可用的要求html
若是才能解決當master服務器宕機後,前端應用自動切換連接呢?前端
最簡單的方式就是給數據庫複製集羣上增長一個虛擬ipmysql
虛擬IP(vip):redis
就是一個未分配給真實主機的ip,也就是說對外提供服務器的主機除了有一個真實IP外還有一個虛擬IPsql
而前端應用程序使用虛擬ip來連接數據庫服務器,當master宕機後,虛擬ip由masterDB遷移到slaveDB上,這樣就不用人爲的修改前端應用的配置了數據庫
設置虛擬IP有不少種方法緩存
除了腳原本實現這些功能,還能夠經過MHA,MMM這樣的集羣管理工具來實現服務器
此處採用keepalived來配置虛擬ip網絡
首先,keepalived能夠提供vip,並對主從數據庫的健康狀態進行監控
當主DB宕機時,遷移VIP到主備數據庫服務器上,這樣就解決了當masterDB宕機時,要手動修改應用服務器的配置,重新鏈接到主備服務器上的問題架構
可是目前還存在一個問題,當master恢復後,因爲當前的寫操做遷移到了從上,因此若是要使用到老的master對新的master(也就是老的slave)進行同步,就不得不從新配置主從複製了,特別是在基於日誌點的複製狀況下,這時候若是咱們數據庫的數據量很是大,在這種狀況下,從新初始化數據也是比較耗時的
因此咱們要對主從複製的架構進行一些更改,改變原來的主從複製爲主主複製,但必定要保證同一個時間只有一個主提供服務,而另外一個主(也就是主備)是處於只讀狀態的,只對外提供讀服務,而不提供寫服務
之前說過InnoDB表的主鍵最好採用自增ID的列,而在主主複製中,爲了不兩個主中同時寫帶來的主鍵衝突,咱們須要修改自增主鍵的一些配置,使兩個主上的自增主鍵按照不一樣的步長進行增加 ,這只是爲了以防萬一採起的一個配置,當咱們使用主主複製時,仍是要保證在任意時間,均只有一個主能夠對外提供服務 ,而另外一個主只提供只讀的服務
master 數據庫配置修改
auto_increment_increment = 2 # 控制自增ID增加的步長,默認爲1 auto_increment_offset = 1 # 控制自增ID從哪一個值開始
這樣修改後,id將會變成1,3,7,9...的形式
主備數據庫配置修改
auto_increment_increment = 2 # 控制自增ID增加的步長,默認爲1 auto_increment_offset = 2 # 控制自增ID從哪一個值開始
這樣修改後,id將會變成2,4,6,8...的形式
Keepalived基於ARRP網絡協議,ARRP能夠將2臺設備虛擬成一個設備,可對外提供一個虛擬IP,也就是咱們架構中的vip,在服務器內部其實是擁有虛擬IP的設備若是正常工做的話就是MASTER設備,同一組內其餘服務器不能用這個虛擬IP,狀態是屬於BACKUP狀態,處於BACKUP狀態的設備,除了接收MASTER的ARRP狀態通告以外,不執行任何對外的服務,當主機失效時,backup將接管原先的master的虛擬IP以及對外提供的各項服務
yum install keepalived -y
在主和主備服務器上都要安裝和配置keepalived
配置文件所在位置
/etc/keepalived/keepalived.conf
配置文件中是按模塊劃分的
! Configuration File for keepalived global_defs { router_id mysql_ha } vrrp_script check_run { script "/etc/keepalived/check_mysql.sh" interval 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 200 priority 99 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1200 } track_script { check_run } virtual_ipaddress { 192.168.3.99/24 } }
vrrp_script模塊中:
定義用於檢查mysql是否運行正常的腳本,以及檢查的時間間隔
vrrp_instance 模塊中:
定義了keepalived服務所處的狀態,這個狀態只有BACKUP和MASTER兩個值
interface :定義了綁定 虛擬ip的網絡接口,必定要是服務器上可用的網絡接口
virtual_router_id :定義了虛擬服務的id,要取0到255之間的數字
priority :定義了優先級,值越高,優先級越大,備份的備設備的值要比主設備低
nopreempt:此值表明不搶佔資源,意思是原來的主宕機後,即便再恢復後也不會把虛擬IP搶回來,對於數據庫來講,這樣能夠避免主從切換的二次傷害的可能
authentication :配置驗證信息,這個在兩個節點必須是一致的
virtual_ipaddress :定義了使用的虛擬ip信息
[client] port = 3306 # 客戶端端口號爲3306 socket = /home/mysql/data/mysql.sock [mysqld] # skip # skip_name_resolve = 1 skip-external-locking =1 # GENERAL # user = mysql # MySQL啓動用戶 default_storage_engine = InnoDB # 新數據表的默認數據表類型 character-set-server = utf8 # #服務端默認編碼(數據庫級別) socket = /home/mysql/data/mysql.sock pid_file = /home/mysql/data/mysqld.pid basedir = /home/mysql #使用該目錄做爲根目錄(Mysql安裝目錄); port = 3306 bind-address = 0.0.0.0 log_error_verbosity = 3 explicit_defaults_for_timestamp = off #sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql_mode = NO_ENGINE_SUBSTITUTION # undo log # innodb_undo_directory = /home.mysql/undo # innodb_undo_tablespaces = 32 # MyISAM # key_buffer_size =32M # SAFETY # max_allowed_packet = 100M max_connect_errors = 1000000 sysdate_is_now =1 #innodb = FORCE #innodb_strict_mode = 1 # Replice # server-id = 100 relay_log = /home/mysql/sql_log/mysqld-relay-bin #plugin-load = semisync_master.so log_slave_updates = on master_info_repository = TABLE relay_log_info_repository =TABLE #######主主複製新增的配置########### auto_increment_increment = 2 # 控制自增ID增加的步長,默認爲1 auto_increment_offset = 1 # 控制自增ID從哪一個值開始 ##################### # gtid_mode = on # enforce_gtid_consistency =on # skip-slave-start =1 #rpl_semi_sync_master_enabled = 1 #rpl_semi_sync_master_timeout=200 # 0.2 second master_info_respository = TABLE # gtid_mode= on # enforce_gtid_consistency = on # skip-slave-start = 1 # DATA STORAGE # datadir = /home/mysql/data #mysql 數據文件存放的目錄 tmpdir = /tmp # MySQL存放臨時文件的目錄 # BINARY LOGGING # log_bin = /home/mysql/sql_log/mysql-bin max_binlog_size = 1000M binlog_format = row expire_log_days = 7 sync_binlog = 1 # CACHES AND LIMITS # tmp_table_size = 32M max_heap_table_size = 32M query_cache_type = 0
auto_increment_increment ,auto_increment_offset 這兩個參數是動態參數,咱們能夠直接經過命令進行修改,不須要重啓
查看並修改
命令以下
mysql> show variables like 'auto%'; mysql> set global auto_increment_increment=2; mysql> set global auto_increment_offset =1;
從服務器配置進行相似修改便可
從服務器配置
[client] port = 3306 # 客戶端端口號爲3306 socket = /home/mysql/data/mysql.sock [mysqld] # skip # skip_name_resolve = 1 skip-external-locking =1 # GENERAL # user = mysql # MySQL啓動用戶 default_storage_engine = InnoDB # 新數據表的默認數據表類型 character-set-server = utf8 # #服務端默認編碼(數據庫級別) socket = /home/mysql/data/mysql.sock pid_file = /home/mysql/data/mysqld.pid basedir = /home/mysql #使用該目錄做爲根目錄(Mysql安裝目錄); port = 3306 bind-address = 0.0.0.0 log_error_verbosity = 3 explicit_defaults_for_timestamp = off #sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql_mode = NO_ENGINE_SUBSTITUTION read_only = on # undo log # innodb_undo_directory = /home.mysql/undo # innodb_undo_tablespaces = 32 # MyISAM # key_buffer_size =32M # SAFETY # max_allowed_packet = 100M max_connect_errors = 1000000 sysdate_is_now =1 #innodb = FORCE #innodb_strict_mode = 1 # Replice # server-id = 101 relay_log = /home/mysql/sql_log/mysqld-relay-bin #plugin-load = semisync_master.so log_slave_updates = on master_info_repository = TABLE relay_log_info_repository =TABLE #######主主複製新增的配置########### auto_increment_increment = 2 # 控制自增ID增加的步長,默認爲1 auto_increment_offset = 2 # 控制自增ID從哪一個值開始 ##################### # gtid_mode = on # enforce_gtid_consistency =on # skip-slave-start =1 #rpl_semi_sync_master_enabled = 1 #rpl_semi_sync_master_timeout=200 # 0.2 second master_info_respository = TABLE # gtid_mode= on # enforce_gtid_consistency = on # skip-slave-start = 1 # DATA STORAGE # datadir = /home/mysql/data #mysql 數據文件存放的目錄 tmpdir = /tmp # MySQL存放臨時文件的目錄 # BINARY LOGGING # log_bin = /home/mysql/sql_log/mysql-bin max_binlog_size = 1000M binlog_format = row expire_log_days = 7 sync_binlog = 1 # CACHES AND LIMITS # tmp_table_size = 32M max_heap_table_size = 32M query_cache_type = 0
mysql> show variables like 'auto%'; mysql> set global auto_increment_increment=2; mysql> set global auto_increment_offset =2;
從服務器查看二進制日誌信息
命令
mysql> show master status \G
能夠查看當前使用的日誌文件
File:mysql-bin:000003
和日誌點
Position:25423894
而後去主服務器上使用change master命令
因爲從到主的複製鏈路以前已開啓過,如今只須要配置主到從的
因爲是主主複製 是把當前的主看成從,把當前的從看成主,在主上配置的master_host的值是從的ip,
命令以下:
mysql> change master to master_host='192.168.2.100', -> master_user='dba_repl', -> master_password='123456', ->MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=25423894; mysql> start slave;
yum install keepalived -y
[root@localhost ~]# cd /etc/keepalived/ [root@localhost keepalived]# ls check_mysql.sh keepalived.bak keepalived.conf
check_mysql.sh 必定要有執行權限
chmod a+x check_mysql.sh
[root@localhost keepalived]# /etc/init.d/keepalived start
啓動成功後,能夠經過ip addr命令查看虛擬ip
能夠經過手動關閉mysql模式宕機,查看主的ip addr中的虛擬Ip已不存在,此時已虛擬Ip在從服務器上
一臺主服務器,一臺從服務器,加入了keepalived服務來監控主從服務器的運行健康狀態,並經過keepalived服務器生成了一個虛擬IP,前端應用是經過虛擬IP來進行數據庫的訪問,而且爲了使主庫宕機後能儘快恢復,把原來的主從複製改成了主主複製
可是目前的讀寫操做還只是所有經過虛擬IP使用同一臺數據庫服務器(主服務器或主備服務器)來進行訪問的,因此這個架構也沒有解決單臺數據庫服務器讀寫壓力大的問題
對於數據庫服務器來講,讀負載和寫負載是兩個不一樣的問題
相對於寫負載,解決讀負載要更容易,由於咱們能夠很容易的獲得多個slave服務器,而且在正常的業務環境中數據庫所執行的讀操做次數要遠遠高於寫操做的次數
同時那些有性能問題的慢查詢,也都是讀操做產生的
解決方式見:如何解決MySQL讀壓力大的問題
MySQL複製沒法緩解寫壓力
利用緩存,合併屢次寫爲一次寫
緩解寫壓力須要對MasterDB進行拆分
前面數據庫操做規範中說過,程序所使用的數據庫帳號只能在同一個數據庫下進行操做,不容許跨庫查詢數據庫
MasterDB中有mc_userdb、mc_productdb、mc_orderdb三個數據庫
創建好新的數據庫集羣后,就能夠在新老集羣之間創建主從同步關係,把要拆分的DB同步到新的集羣中
即 把mc_productdb同步到商品集羣中 ,mc_orderdb同步到訂單集羣中
當數據庫同步成功後,找一個業務的低峯時間段,好比凌晨三、4點時,把老集羣上數據庫的帳號,遷移到新的數據庫集羣中
遷移成功後,修改老集羣的應用在老集羣數據庫上的連接,把
對mc_productdb和mc_orderdb上的連接修改到新的集羣上