最近在總結研究下之前項目涉及的高可用方案的東西,已經完成了WEB的HA,這裏開始準備總結下數據庫的,因此先以之前使用的MYSQL入手,MYSQL的高可用方案最流行的就是複製模式,主要有半同步和同步模式,性價比最高和應用最多的仍是半同步,本文總結和記錄下半同步的安裝和配置。html
本案例先使用兩臺linux作雙機MASTER-MASTER高可用(後續能夠考慮加入只讀SLAVER,用於提升查詢性能),採用MYSQL5.6.x的半同步實現數據複製和同步,使用keepalived來監控MYSQL和提供VIP及浮動。前端
操做系統:RedHat 6.3 mysql
Keepalived:keepalived-1.2.2.tar.gz linux
MYSQL:MySQL-server-5.6.10-1.el6.x86_64.rpm MySQL-client-5.6.10-1.el6.x86_64.rpmsql
名稱 | IP | 備註 |
VIP | 10.10.10.20 | 由KEEPALIVED產生的虛擬IP,也是前端客戶端使用的IP |
MYSQL_DB_MASTER1 | 10.10.10.21 | 數據庫1服務器(默認主) |
MYSQL_DB_MASTER2 | 10.10.10.22 | 數據庫2服務器 |
3.一、安裝MYSQL數據庫
這裏選擇的是使用社區版的MYSQL,請在www.mysql.com上下載對應操做系統的安裝文件,這裏根據官方的建議使用RPM包方式安裝。vim
安裝bash
若是是默認Redhat6.3安裝後,可能會有mysql-libs的衝突,請先卸載原有的mysql-libs相關包。服務器
# yum -y remove mysql-libs*網絡
# rpm -ivh MySQL-server-5.6.10-1.el6.x86_64.rpm
……
# rpm -ivh MySQL-client-5.6.10-1.el6.x86_64.rpm
……
默認安裝是在/usr下面,因此my.cnf是在/usr/my.cnf,這裏爲了習慣用法,拷貝到/etc/目錄下
# mv /usr/my.cnf /etc/
設置root用戶初始密碼
默認安裝完成後,mysql的root初始密碼保存在: ~/.mysql_secret
# cat ~/.mysql_secret
# The random password set for the root user at Tue Dec 17 19:31:29 2013 (local time): uQ8X91Ys
標準方式修改密碼
# mysqladmin -u root -p oldPassword password
# New password:
# Confirm new password:
或
# mysqladmin -u root -p password newPassword
SQL直接更新方式修改密碼:
初始化root密碼常見問題及處理 error: 'Access denied for user 'root'@'localhost' (using password: NO)' # /etc/init.d/mysql stop # mysqld_safe --user=mysql --skip-grant-tables --skip-networking & # mysql -u root mysql mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root'; mysql> FLUSH PRIVILEGES; mysql> quit # /etc/init.d/mysql restart # mysql -uroot -p Enter password: <輸入新設的密碼newpassword> mysql> |
設置網絡訪問權限
MYSQL的用戶訪問策略是須要指定用戶從某IP能夠訪問那些權限。具體用法請參考grant命令。這裏爲了簡單起見,直接設置root用戶在整個局域內(10.10.10.*)均可以訪問數據庫。
# mysql -uroot -p
******
mysql> GRANT ALL PRIVILEGES ON *.* TO root@'10.10.10.%' IDENTIFIED BY 'password' WITH GRANT OPTION;
mysql>FLUSH PRIVILEGES;
這樣設置後,就能夠經過內網的其餘機器訪問數據庫了。
修改數據文件路徑
mysql安裝後,默認的數據存儲路徑在/var/lib/mysql下。這裏修改成/data/mysql
# service mysql stop
# mkdir /data/mysql
# cp -r /var/lib/mysql/* /data/mysql
# chown -R mysql:mysql /data/mysql
vi /etc/my.cnf
[mysqld] datadir = /data/mysql socket = /data/mysql/mysql.sock # 順便配置下MYSQL使用mysql用戶啓動 user=mysql
保存退出
爲/data/mysql/mysql.sock創建指向/var/lib/mysql/mysql.sock的軟鏈接
# ln -s /data/mysql/mysql.sock /var/lib/mysql/mysql.sock
啓動MYSQL並測試
# service mysql start
# mysql -uroot -p
******
mysql>
最可能出現的問題(若是你是Redhat6.x或CentOS6.x):selinux 照成服務沒法正常啓動,報錯:
Starting MySQL. ERROR! The server quit without updating PID file (/data/mysql/xxxxx.pid).
驗證問題方法:
# setenforce 0
# service mysql start
Starting MySQL. SUCCESS!
若是能正常啓動,解決問題,就肯定是selinux形成的問題了。
解決辦法1:直接禁用
vim /etc/selinux/config
修改:SELINUX=disabled
保存後,重啓操做系統生效
解決方案2:配置selinux支持mysql訪問相關端口和文件系統
本人比較懶,給個鏈接本身研究哈(或者google: selinux mysql):
https://blogs.oracle.com/jsmyth/entry/selinux_and_mysql
若是出現問題,通常解決問題的方式是查看MYSQL的日誌文件,通常提示會比較清楚,或者根據錯誤信息區GOOGLE均可以找到答案。日誌文件: ${datadir}/${hostname}.err, 本例中修改了數據目錄,因此日誌文件是:/data/mysql/acooly1.err
OK,本節安裝MYSQL完成,而後另一臺服務器的MYSQL安裝徹底相同(半同步的設置有小不一樣,那下面會說明)。請參照以上說明安裝另一臺MYSQL服務(MYSQL_DB_MASTER2)。
半同步複製及semi-sync replication,最開始是GOOGLE提出和實現,後來MYSQL在5.5後的版本中支持的複製功能。只要是經過相似「兩階段提交」的方式實現,只要有一臺備機成功同步數據,主服務器的事務就提交,不然等待10秒後,轉爲傳統的異步複製。
本方案中爲了實現故障轉移功能,在利用半同步複製能力的同時,對總體方案進行了調整以下:
配置/etc/my.cnf
分別修改/etc/my.cnf配置,打開bin-log功能和設置server_id
vi /etc/my.cnf
[mysqld] # MYSQL_DB_MASTER1設置爲1,MYSQL_DB_MASTER2設置爲2 server_id=1 log_bin=mysql-bin
安裝官方文檔說明,主(MYSQL_DB_MASTER1)須要設置rpl_semi_sync_master_enabled=1和rpl_semi_sync_master_timeout=1000,備(MYSQL_DB_MASTER2)須要設置rpl_semi_sync_slave_enabled=1,這裏由於是雙向同步,我都沒有設置,經測試,沒有設置也沒有關係(暫時沒有深究,後續在研究下)。
配置MYSQL_DB_MASTER1與MYSQL_DB_MASTER2的主備同步
在MYSQL_DB_MASTER1上操做配置MYSQL_DB_MASTER1爲MYSQL_DB_MASTER2的主。
# mysql -uroot -p Enter password: ...... -- 創建複製用戶replication,容許內網內其餘機器(訪問本機全部數據庫) mysql > grant replication slave on *.* to 'replication'@'10.10.10.%' identified by 'replication'; Query OK, 0 rows affected (0.00 sec) -- 查看master的bin-log狀態,用戶設置SLAVE同步的起點 mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000013 | 120 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.02 sec)
這裏注意記錄下當前bin-log文件名稱:mysql-bin.000013和位置:120,備機設置的時候須要用到。
在MYSQL_DB_MASTER2上操做配置
--設置SLAVE的MASTER和開始同步的文件位置 mysql> change master to master_host='10.10.10.21',master_user='replication',master_password='replication',master_log_file='mysql-bin.000003',master_log_pos=120; --啓動同步 mysql> start slave; mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.10.10.21 Master_User: replication Master_Port: 3306 Connect_Retry: 10 Master_Log_File: mysql-bin.000013 Read_Master_Log_Pos: 120 Relay_Log_File: acooly2-relay-bin.000020 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql-bin.000013 Slave_IO_Running: Yes Slave_SQL_Running: Yes …… 1 row in set (0.02 sec)
Slave_IO_Running: Yes和Slave_SQL_Running: Yes表示SLAVE已經正常啓動並監聽MASTER的數據發送事件,處理同步。
配置MYSQL_DB_MASTER2與MYSQL_DB_MASTER1的主備同步
全部配置操做與上一節,只是把主備關係交換。
OK
若是全部的配置成功,啓動MASTER1和MASTER2兩個數據庫,分別從兩端建立數據庫,表和更新表數據,另一邊都會實時同步。
前面已經完成MYSQL的雙向實時同步的配置,本節使用Keepalived實現MYSQL雙機的高可用,故障轉移。經過VIP實現同時只有一臺MYSQL提供服務。
兩臺MYSQL服務器上的配置基本相同(除了keepalived.conf的個別配置外),具體操做配置以下:
安裝Keepalived請參考:Keepalived + LVS(DR) 高可用負載均衡集羣 的 3.三、Keepalived 安裝配置
設置keepalived的主配置文件/etc/keepalived/keepalived.conf實現本機的MYSQL的監控和VIP浮動。
global_defs { router_id Mysql-HA } # 定義MYSQL監控的腳本,每2秒監控一次,具體腳本請見下面 vrrp_script check_mysql { script "/opt/keepalived/keepalived_check_mysql.sh" interval 2 } vrrp_sync_group VG1 { group { KEEPALIVED_MYSQL } } vrrp_instance KEEPALIVED_MYSQL { # 注意:兩臺MYSQL服務器都設置爲BACKUP state BACKUP interface eth0 virtual_router_id 20 # MASTER1設置爲100,則MASTER2設置爲稍低,如:90 priority 100 advert_int 1 # 只有MASTER1設置不搶奪控制權 nopreempt authentication { auth_type PASS auth_pass 111111 } track_script { check_mysql } virtual_ipaddress { 10.10.10.20 } }
檢查本機MYSQL服務是否正常,若是MYSQL服務不可用,則中止KEEPALIVED服務,由備機的KEEPALIVED接管並提供VIP(指向備機)
#!/bin/bash MYSQL=/usr/bin/mysql MYSQL_HOST=localhost MYSQL_USER=root MYSQL_PASSWORD=1qaz@WSX # 日誌文件 LOG_FILE=/opt/keepalived/check_mysql.log # 檢查次數 CHECK_TIME=3 #mysql is working MYSQL_OK is 1 , mysql down MYSQL_OK is 0 MYSQL_OK=1 function check_mysql_helth (){ $MYSQL -h $MYSQL_HOST -u $MYSQL_USER -p${MYSQL_PASSWORD} -e "show status;" >/dev/null 2>&1 if [ $? = 0 ] ;then MYSQL_OK=1 else MYSQL_OK=0 fi return $MYSQL_OK } while [ $CHECK_TIME -ne 0 ] do let "CHECK_TIME -= 1" check_mysql_helth if [ $MYSQL_OK = 1 ] ; then CHECK_TIME=0 #echo `date --date=today +"%Y-%M-%d %H:%m:%S"` - [INFO] - mysql available: success[$MYSQL_OK] >> $LOG_FILE exit 0 fi if [ $MYSQL_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ] then /etc/init.d/keepalived stop echo `date --date=today +"%Y-%M-%d %H:%m:%S"` - [INFO] - mysql invaild. keepalived stop. >> $LOG_FILE exit 1 fi sleep 1 done
配置完成後,分別啓動兩臺服務器的mysql和keepalived服務
分別啓動MYSQL_DB_MASTER1和MYSQL_DB_MASTER2
# service mysql start
Starting MySQL.......... SUCCESS!
# service keepalived start
Starting keepalived: [ OK ]
在MYSQL_DB_MASTER1查看VIP
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
……
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:50:56:3b:be:91 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.21/24 brd 10.10.10.255 scope global eth0
inet 10.10.10.20/32 scope global eth0
inet6 fe80::250:56ff:fe3b:be91/64 scope link
valid_lft forever preferred_lft forever
中止MYSQL_DB_MASTER1的MYSQL服務,查看VIP
# service mysql stop
Shutting down MySQL..... SUCCESS!
# service keepalived status
keepalived is stopped
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
……
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:37:87:e4 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.21/24 brd 10.10.10.255 scope global eth0
inet6 fe80::20c:29ff:fe37:87e4/64 scope link
valid_lft forever preferred_lft forever
沒有VIP(10.10.10.20)了
在MYSQL_DB_MASTER2上查看VIP
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
……
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:50:56:3b:be:91 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.22/24 brd 10.10.10.255 scope global eth0
inet 10.10.10.20/32 scope global eth0
inet6 fe80::250:56ff:fe3b:be91/64 scope link
valid_lft forever preferred_lft forever
能夠看到VIP已經切換到MYSQL_DB_MASTER2
重新啓動MYSQL_DB_MASTER1的MYSQL服務和KEEPALIVED服務,可是這個時候是不會重新浮動到MASTER1的,由於咱們配置KEEPALIVED的時候都是配置的BACKUP,並且MASTER1配置了不搶佔。這餘咱們設計是相符的。(只有等MASTER2出現故障的狀況才重新有MASTER1接管)
OK,本次記錄到此,後續完善加入多個異步同步的SLAVE。
http://bbs.chinaunix.net/thread-1824528-1-1.html
http://blog.csdn.net/haier_jiang/article/details/8449013
http://www.9ai9.net/?p=131