本文目錄:html
2.mycat全局表java
3.mycat讀寫分離node
4.mycat分片規則mysql
5.E-R表linux
6.HAProxyc++
8.Keepalivedredis
1.解壓 tar -zxvf Mycat-server-1.6.7.3-release-20190828135747-linux.tar.gz 2. 爲了更好的看目錄結構,安裝tree yum -y install tree # 查詢mycat的目錄結構,個人mycat是安裝在study下的 tree /study/mycat 3. 設置MYCAT_HOME的變量(若是沒有安裝jdk,還須要安裝jdk): vi /etc/profile export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar export PATH=$PATH:${JAVA_HOME}/bin export MYCAT_HOME=/study/mycat 4.刷新使變量生效: source /etc/profile 5.設置 wrapper.java.command 的java 路徑(mycat的conf目錄下): vi wrapper.conf wrapper.java.command=%JAVA_HOME%/bin/java 6.修改server.xml(開啓實時統計,便於後期安裝mycat-eye的監測): <!-- 1爲開啓實時統計、0爲關閉 --> <property name="useSqlStat">1</property> 7.修改schema.xml:
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <!--schema表示當前mycat維護的一個邏輯庫相關配置,邏輯庫中能夠包含多個邏輯庫--> <mycat:schema xmlns:mycat="http://io.mycat/"> <!--邏輯庫:客戶端鏈接mycat,能夠看到的全部庫並非真實的數據庫資源而是mycat通過資源整合以後 容許客戶端查看到的schema邏輯庫,用戶是否有權限查看到邏輯庫,取決於server.xml中的配置的用戶屬性schemas, 對應的就是這個schema標籤的name--> <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100"> <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /> <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" /> <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long" /> <table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" /> <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id"> <childTable name="order_items" joinKey="order_id" parentKey="id" /> </childTable> <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" /> </table> <!--測試配置一個邏輯表--> <table name="test_table" primaryKey="id" dataNode="dn1"></table> </schema> <!--配置mycat的分片節點--> <dataNode name="dn1" dataHost="localhost1" database="test" /> <dataNode name="dn2" dataHost="localhost1" database="test_mycat" /> <dataNode name="dn3" dataHost="localhost1" database="test" /> <dataHost name="localhost1" 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="localhost:3306" user="root" password="****"> <!-- can have multi read hosts --> <readHost host="hostS2" url="localhost:3306" user="root" password="****" /> </writeHost> </dataHost> </mycat:schema>
7.配置完成後,能夠運行./mycat console 查詢配置是否出錯(mycat的bin目錄下) 8.啓動mycat: ./mycat start 9.啓動mysql,下面的-h後面的ip替換成本身的,密碼是在server.xml裏面配置的root的密碼: mysql -uroot -p -P8066 -h192.168.189.150 -DTESTDB --default_auth=mysql_native_password
我這裏使用的test_table表,在mycat裏面插入一條數據:算法
而後使用navicat打開個人數據庫,能夠看到剛剛insert的數據已經插入進去了:
在項目中,總會一部分字典項等數據,這種數據通常數據量不會很大,並且改動也比較少。在mycat中將這種表稱之爲全局表,一般這種表能夠不須要進行拆分,每一個分片都建立一張相同的表,在全部的分片上都保存一份數據。在進行插入、更新、刪除的時候,會將sql語句發送到全部的分片上執行,在進行查詢時,也會把sql發送到各個分片上。這樣避免了跨庫的關聯操做,直接與本分片上的全局表進行聚合操做。
create database test_global01; use test_global01; CREATE TABLE `order_status` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`status_name` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; create database test_global02; use test_global02; CREATE TABLE `order_status` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`status_name` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; create database test_global03; use test_global03; CREATE TABLE `order_status` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`status_name` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在schema.xml裏配置一個表,和真實數據庫表要對應,要將三個分片都包含進去。 type="global"這個表示全局表,必填。注意分片節點最好設置不同,若是分片節點設置相同的,可能會出如今mycat上插入了一次,但在sql上卻執行了幾回的狀況,即在數據庫中多條記錄。
<table name="order_status" dataNode="dn$1-3" primaryKey="id" type="global"></table> <!--配置mycat的分片節點--> <dataNode name="dn1" dataHost="localhost1" database="test_global01" /> <dataNode name="dn2" dataHost="localhost1" database="test_global02" /> <dataNode name="dn3" dataHost="localhost1" database="test_global03" />
insert into order_status(status_name) values ('ORDER_NOT_PAY'); insert into order_status(status_name) values ('ORDER_PAY'); insert into order_status(status_name) values ('ORDER_FINISH');
使用explain查看mycat的插入能夠看到,對三個分片都進行了執行
mysql> explain insert into order_status(status_name) values ('ORDER_PAY'); +-----------+------------------------------------------------------------+ | DATA_NODE | SQL | +-----------+------------------------------------------------------------+ | dn1 | insert into order_status(status_name) values ('ORDER_PAY') | | dn2 | insert into order_status(status_name) values ('ORDER_PAY') | | dn3 | insert into order_status(status_name) values ('ORDER_PAY') | +-----------+------------------------------------------------------------+ 3 rows in set (0.00 sec)
在從庫的mysql上查看test_gloabl02的數據:
mysql> use test_global02; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from order_status; +----+---------------+ | id | status_name | +----+---------------+ | 1 | ORDER_NOT_PAY | | 2 | ORDER_PAY | | 3 | ORDER_FINISH | +----+---------------+ 3 rows in set (0.00 sec)
執行查詢能夠看出,查詢時在隨機節點上執行,插入,更新時會把sql語句發送到全部分片節點上執行。
mysql> explain select * from order_status; +-----------+--------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------+ | dn2 | SELECT * FROM order_status LIMIT 100 | +-----------+--------------------------------------+ 1 row in set (0.00 sec) mysql> explain select * from order_status; +-----------+--------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------+ | dn3 | SELECT * FROM order_status LIMIT 100 | +-----------+--------------------------------------+ 1 row in set (0.00 sec) mysql> explain select * from order_status; +-----------+--------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------+ | dn1 | SELECT * FROM order_status LIMIT 100 | +-----------+--------------------------------------+ 1 row in set (0.01 sec)
1.writeType標籤:有兩個值(0/1),取值決定於 寫/讀寫 的邏輯
0:表示當前dataHost接受到分片的讀寫操做中,寫操做,只在第一個writeHost;
1:表示隨機的讀寫全部的writeHost和readHost中實現,覆蓋balance的邏輯
2.balance標籤:控制一個dataHost中全部的邏輯,一旦writeType=1,就無效了。
0:不開啓讀寫分離,直在第一個writeHost執行,其餘的readHost,writeHost都不進行讀的操做
1:除了第一個writeHost之外的全部writeHost和readHost進行隨機讀取,在高併發時,若是其餘節點都高負荷的運轉進行讀操做,也有一部分的讀被分配到第一個writeHost上
2:隨機的在全部節點進行讀取
3:到全部的readHost當中讀取數據,若是分片中不存在readHost,只會到第一個writeHost上讀取
讀寫分離的測試,仍是在schema.xml裏配置,下面是筆者的配置(150是主庫,15一、152是從庫):
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" 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.189.150:3306" user="root" password="zj005200.."> <readHost host="hostS2" url="192.168.189.151:3306" user="root" password="zj005200.." /> <readHost host="hostS3" url="192.168.189.152:3306" user="root" password="zj005200.." /> </writeHost> </dataHost>
執行能夠看到,查詢是隨機在兩臺從庫上執行:
mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 2 | +---------------+-------+ 1 row in set (0.01 sec) mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 3 | +---------------+-------+ 1 row in set (0.01 sec)
rule屬性:對於一個指定了分片的表格,能夠配置rule屬性,根據名稱定義分片的計算規則。
如:schema.xml文件裏配置的:
<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
在rule.xml文件中的:
<tableRule name="auto-sharding-long"> <rule> <columns>id</columns>//當前的算法使用的字段名稱,若是是不一樣的,能夠在標籤中修改 <algorithm>rang-long</algorithm>//算法名稱,rang-long指向了函數function標籤 </rule> </tableRule> <function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">//class表明執行代碼類 <property name="mapFile">autopartition-long.txt</property>//計算輔助文件,在conf下有這個文件 </function>
下面是文件的內容:
# range start-end ,data node index # K=1000,M=10000. 0-500M=0 --表示若是數據在0~500萬之間,會插入到第一個分片中(含頭不含尾) 500M-1000M=1 --表示若是數據在500~1000萬之間,會插入到第二個分片中(含頭不含尾) 1000M-1500M=2
自定義分片規則(以城市分片):
schema.xml添加表: <!--測試分片規則的表--> <table name="t_city" dataNode="dn$1-3" rule="sharding-by-intfile-test"/> rule.xml自定義tableRule: <!--自定義分片規則--> <tableRule name="sharding-by-intfile-test"> <rule> <columns>city</columns> <algorithm>hash-int-test</algorithm> </rule> </tableRule> <function name="hash-int-test" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int-test.txt</property> <!--0:integer 非0表示string--> <property name="type">1</property> <!--設置默認節點,默認節點的做用:枚舉分片時,若是碰到不識別的枚舉值,就讓他進入默認節點,不配置可能會報錯,小於 0 表示不設置默認節點,大於等於 0 設置默認節點--> <property name="defaultNode">0</property> </function> 添加一個partition-hash-int-test.txt: hubei=0 guangdong=1 chongqing=2 DEFAULT_NODE=0
在mysql中建立表:
use test_global01; CREATE TABLE `t_city` (`id` varchar(20) NOT NULL,`city` varchar(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; use test_global02; CREATE TABLE `t_city` (`id` varchar(20) NOT NULL,`city` varchar(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; use test_global03; CREATE TABLE `t_city` (`id` varchar(20) NOT NULL,`city` varchar(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
啓動mycat,並插入數據:
mysql> insert into t_city(id,city) values (database(),'hubei'); Query OK, 1 row affected (0.03 sec) mysql> insert into t_city(id,city) values (database(),'guangdong'); Query OK, 1 row affected (0.02 sec) mysql> insert into t_city(id,city) values (database(),'chongqing'); Query OK, 1 row affected (0.01 sec) mysql> insert into t_city(id,city) values (database(),'hainan'); Query OK, 1 row affected (0.01 sec) mysql> select * from t_city; +---------------+-----------+ | id | city | +---------------+-----------+ | test_global01 | hubei | | test_global02 | guangdong | | test_global03 | chongqing | | test_global01 | hainan | +---------------+-----------+ 4 rows in set (0.00 sec)
如圖所示:上面的插入,將hubei插入第一個分片,guangdong插入第二個分片,chongqing插入第三個分片,同時,hainan則插入到默認節點裏。
因爲mycat底層不支持跨分片操做,若是需求中有多個相關的分片表進行關聯操做時,就須要如E-R分片的配置邏輯。 基於E-R關係進行分片,子表的記錄與其父表的記錄保存在同一個分片上,這樣關聯就不須要跨庫進行查詢了。
在schema.xml配置文件中schema標籤中配置customer table 的分庫策略
<!-- ER表配置示例--> <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id"> <childTable name="order_items" joinKey="order_id" parentKey="id" /> </childTable> <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" /> </table> <!--若是須要配置多個分片,則須要修改rule.xml中,設置count 多少個分片 <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="count">3</property> </function>-->
配置說明: table標籤代表這是配置表信息; name = "customer" 說明這張表的名稱叫customer, id 是 主鍵, 表分佈在dn1,dn2,dn3這三個數據庫中, 表的分片策略是sharding-by-intfile.
childTable代表子表信息, 此示例中說明customer關聯了兩張子表,分別是orders,customer_addr;咱們以orders表爲例說明.
orders表的主鍵是id,它經過joinKey關聯父表的parentKey.本例中orders表就是以customer_id去關聯customer表的id.也就是說,當customer表中id = 1 在dn1時,那麼orders表中customer_id = 1這條數據也會在dn1這個數據庫. 這樣設置就避免了跨庫join,提升了查詢效率.
一樣的,order_items表關聯的父表是orders. 原理同樣.
# 啓動後,建立表 create table customer(id int not null primary key,name varchar(100),company_id int not null,sharding_id int not null); create table orders (id int not null primary key ,customer_id int not null,sataus int ,note varchar(100) ); create table order_items (id int not null primary key ,order_id int not null,remark varchar(100) ); # 插入數據 insert into customer (id,name,company_id,sharding_id )values(1,'wang',1,10000); insert into customer (id,name,company_id,sharding_id )values(2,'xue',2,10010); insert into customer (id,name,company_id,sharding_id )values(3,'feng',3,10000); insert into customer (id,name,company_id,sharding_id )values(4,'test',4,10010); insert into customer (id,name,company_id,sharding_id )values(5,'admin',5,10010); insert into orders(id,customer_id) values(1,1); insert into orders(id,customer_id) values(2,2); insert into orders(id,customer_id,sataus,note) values(3,4,2,'xxxx'); insert into orders(id,customer_id,sataus,note) values(4,5,2,'xxxx'); insert into order_items(id,order_id,remark) VALUES (1,1,'1mark'); insert into order_items(id,order_id,remark) VALUES (2,2,'2mark'); insert into order_items(id,order_id,remark) VALUES (3,3,'3mark'); insert into order_items(id,order_id,remark) VALUES (4,4,'4mark');
以下圖所示:使用navicat查詢, 基於E-R關係進行分片,子表的記錄與其父表的記錄保存在同一個分片上,這樣關聯就不須要跨庫進行查詢了。
筆者使用的環境:
服務器名稱 | ip | 操做系統 | 安裝軟件 |
---|---|---|---|
mysql-master | 192.168.189.150 | CentOS7.1 | mysql.mycat,keepalived |
mysql-slave1 | 192.168.189.151 | CentOS7.1 | mysql.mycat,haproxy,keepalived |
mysql-slave2 | 192.168.189.152 | CentOS7.1 | mysql.mycat,keepalived |
HAProxy的安裝很是簡單:yum install -y haproxy
查看安裝的haproxy: rpm -qi haproxy
安裝完成後的目錄:cd /usr/sbin
配置文件的目錄:cd /etc/haproxy/
1.HAProxy的配置文件由兩部分構成:
全局設定(global settings):主要用於定義HAProxy進程管理安全及性能相關的參數
對代理的設定(proxies):共分爲4段(defaults,frontend,backend,listen)
defaults:爲除了global之外的其餘配置段提供默認參數,默認配置參數可由下一個defaults從新設定
frontend:定義一系列監聽的套接字,這些套接字可接受客戶端請求並與之創建鏈接
backend:定義「後端」服務器,前端代理服務器將會把客戶端的請求調度至這些服務器
listen:定義監聽的套接字和後端的服務器,相似於將frontend和backend段放在一塊兒,一般只對TCP流量有用, 全部代理的名稱只能使用大寫字母、小寫字母、數字、-(中線)、_(下劃線)、.(點號)、:(冒號),而且ACL區分字母大小寫
配置haproxy配置文件,目錄:/etc/haproxy/haproxy.cfg
這裏筆者把本身已經配置好的的配置文件貼出來:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode tcp log global option tcplog option dontlognull option http-server-close #option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend mycat bind 0.0.0.0:8066 mode tcp log global default_backend mycat_server #--------------------------------------------------------------------- # static backend for serving up images, stylesheets and such #--------------------------------------------------------------------- backend mycat_server balance roundrobin server mycat1 192.168.189.151:8066 check inter 5s rise 2 fall 3 server mycat2 192.168.189.152:8066 check inter 5s rise 2 fall 3 #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- listen stats mode http bind 0.0.0.0:1080 stats enable stats hide-version stats uri /Haproxyadmin?stats stats realm Haproxy\ Statistics stats auth admin:admin stats admin if TRUE
在這裏解釋一下三個配置:
#option forwardfor except 127.0.0.0/8 --若是後端服務器須要獲取真實ip,就須要配置的參數 balance roundrobin --負載方式:輪詢 server mycat1 192.168.189.151:8066(mycat的ip和端口) check inter 5s(檢測心跳時間) rise 2 fall 3(失敗重連次數)
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg
查看進程,若是看到以下則提示配置成功:
[root@localhost haproxy]# ps -ef|grep haproxy haproxy 7512 1 0 09:02 ? 00:00:00 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg root 7516 7393 0 09:02 pts/0 00:00:00 grep --color=auto haproxy
關閉防火牆:
systemctl stop firewalld
在瀏覽器上訪問(鏈接地址:http://192.168.189.151:1080/Haproxyadmin?stats 帳號/密碼:上面listen中配置的admin/admin),若是看到以下頁面,就表示已經成功:
輪詢:順序循環將請求依次順序循環地鏈接每一個服務器。當其中某個服務器發生第二到第7層的故障,BIG-IP就把其從順序循環隊列中拿出,不參加下一次的輪詢,直到其恢復正常。
比率:給每一個服務器分配一個加權值爲比例,根椐這個比例,把用戶的請求分配到每一個服務器。當其中某個服務器發生第二到第7層的故障,BIG-IP 就把其從服務器隊列中拿出,不參加下一次的用戶請求的分配, 直到其恢復正常。
優先權:給全部服務器分組,給每一個組定義優先權,BIG-IP 用戶的請求,分配給優先級最高的服務器組;當最高優先級中全部服務器出現故障,BIG-IP 纔將請求送給次優先級的服務器組。這種方式,實際爲用戶提供一種熱備份的方式。
(1)高性能:負載均衡技術將業務較均衡的分擔到多臺設備或鏈路上,從而提升了整個系統的性能;
(2)可擴展性:負載均衡技術能夠方便的增長集羣中設備或鏈路的數量,在不下降業務質量的前提下知足不斷增加的業務需求;
(3)高可靠性:單個甚至多個設備或鏈路出現故障也不會致使業務中斷,提升了整個系統的可靠性;
(4)可管理性:大量的管理共組都集中在使用負載均衡技術的設備上,設備集羣或鏈路集羣只須要維護經過的配置便可;
(5)透明性:對用戶而言,集羣等於一個或多個高可靠性、高性能的設備或鏈路,用戶感知不到,也不關心具體的網絡結構,增長或減小設備或鏈路數量都不會影響正常的業務。
keepalived,保持存活,就是高可用設備或熱備用來防止單點故障的發生,keepalived經過請求一個vip來達到請求真實ipi地址的功能,而vip可以在一臺機器發生故障的時候,自動漂移到另一臺機器上,歷來達到了高可用HAProxy的功能。
keepalived的實現基於VRRP實現的保證集羣高可用的一個服務軟件,主要功能是實現真機的故障隔離和負載均衡器間的失敗切換,防止單點故障。
VRRP協議:Virtual Route Redundancy Protocol虛擬路由冗餘協議。是一種容錯協議,保證當主機的下一跳路由出現故障時,由另外一臺路由器來代替出現故障的路由器進行工做,從而保持網絡通訊的連續性和可靠性。在介紹VRRP以前先介紹一些關於VRRP的相關術語:
虛擬路由器:由一個 Master 路由器和多個 Backup 路由器組成。主機將虛擬路由器看成默認網關。
VRID:虛擬路由器的標識。有相同 VRID 的一組路由器構成一個虛擬路由器。
Master 路由器:虛擬路由器中承擔報文轉發任務的路由器。
Backup 路由器: Master 路由器出現故障時,可以代替 Master 路由器工做的路由器。
虛擬 IP 地址:虛擬路由器的 IP 地址。一個虛擬路由器能夠擁有一個或多個IP 地址。
IP 地址擁有者:接口 IP 地址與虛擬 IP 地址相同的路由器被稱爲 IP 地址擁有者。
虛擬 MAC 地址:一個虛擬路由器擁有一個虛擬 MAC 地址。虛擬 MAC 地址的格式爲 00-00-5E-00-01-{VRID}。一般狀況下,虛擬路由器迴應 ARP 請求使用的是虛擬 MAC 地址,只有虛擬路由器作特殊配置的時候,纔回應接口的真實 MAC 地址。
優先級: VRRP 根據優先級來肯定虛擬路由器中每臺路由器的地位。
非搶佔方式:若是 Backup 路由器工做在非搶佔方式下,則只要 Master 路由器沒有出現故障,Backup 路由器即便隨後被配置了更高的優先級也不會成爲Master 路由器。
搶佔方式:若是 Backup 路由器工做在搶佔方式下,當它收到 VRRP 報文後,會將本身的優先級與通告報文中的優先級進行比較。若是本身的優先級比當前的 Master 路由器的優先級高,就會主動搶佔成爲 Master 路由器;不然,將保持 Backup 狀態。
keepalived是模塊化設計,不一樣模塊負責不一樣的功能,core模塊爲keepalived的核心,負責主進程的啓動、維護以及全局配置文件的加載和解析。checkers負責健康檢查,包括常見的各類檢查方式。VRRP模塊是來實現VRRP協議的。
cd /home # 安裝環境依賴 yum install gcc gcc-c++ openssl openssl-devel # 若是沒有安裝過wget, yum install wget 安裝 wget -q https://www.keepalived.org/software/keepalived-1.2.18.tar.gz # ls查看是否安裝了 keepalived-1.2.18.tar.gz tar -zxvf keepalived-1.2.18.tar.gz cd keepalived-1.2.18 # 監測 ./configure --prefix=/usr/local/keepalived-1.2.18/ # 編譯安裝 make && make install
# 由於沒有使用keepalived的默認路徑安裝(默認是/usr/local),安裝後,須要複製默認配置文件到默認路徑下 mkdir /etc/keepalived cp /usr/local/keepalived-1.2.18/etc/keepalived/keepalived.conf /etc/keepalived/ # 將初始化文件複製到etc裏 cp /usr/local/keepalived-1.2.18/etc/rc.d/init.d/keepalived /etc/init.d # 將配置文件複製到etc裏 cp /usr/local/keepalived-1.2.18/etc/sysconfig/keepalived /etc/sysconfig # 軟鏈接 ln -s /usr/local/keepalived-1.2.18/sbin/keepalived /usr/sbin/ # 將keepalived設置爲開機啓動 chkconfig keepalived on
cd /etc/keepalived/ # 修改配置文件,建議下載下來修改 vi keepalived.conf # 下面是主keepalived.conf的配置文件 ! Configuration File for keepalived global_defs { # 全局配置標識,代表這個區域是全局配置 router_id LVS_MASTER } vrrp_sync_group VG1 { group { VI_1 } } # keepalived會去檢測負載均衡器,因此要設定一個腳本,讓他本身去檢測 vrrp_script chk_haproxy { # 檢測haproxy狀態的腳本路徑 script "/etc/keepalived/haproxy_check.sh" # 檢測間隔時間 interval 2 # 若是條件成立,權重+2,反之 -2 weight 2 } # 定義一種虛擬路由協議,即vrrp,一個vrrp_instance 定義一個虛擬路由器,VI_1實例名 vrrp_instance VI_1 { # 定義初始狀態,樂意是master或者backup(備份) state MASTER # 工做接口,通告選舉使用哪一個接口進行,使用ip addr查看 interface ens33 # 虛擬路由id,若是是一組,則定義一個id,若是是多組,則定義多個 virtual_router_id 51 # 優先級策略選擇參數 priority 100 # 通告頻率單位是s advert_int 1 # 通訊認證機制 authentication { auth_type PASS auth_pass 1111 } # 虛擬路由ip網段不同,設置本身的網段+ip virtual_ipaddress { 192.168.189.100 } # 檢測腳本 對應的是vrrp_script chk_haproxy 負載均衡器 track_script{ chk_haproxy } } # 從keepalived.conf的配置文件: global_defs { #備用 router_id LVS_BACKUP } vrrp_sync_group VG1 { group { VI_1 } } vrrp_script chk_haproxy { script "/etc/keepalived/haproxy_check.sh" interval 2 weight 2 } vrrp_instance VI_1 { # 狀態爲備用的狀態 state BACKUP interface ens33 virtual_router_id 51 # 優先級不能高於主 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.189.100 } track_script{ chk_haproxy } }
#!/bin/bash START_HAPROXY="/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg" LOG_FILE="/usr/local/keepalived/log/haproxy-check.log" # 日誌文件,會新建一個日誌文件 HAPS=`ps -C haproxy --no-header |wc -l` # 檢測狀態,0表示未啓動,1表示啓動 date "+%Y-%m-%d %H:%M:%S" >> $LOG_FILE # 記錄時間 echo "check haproxy status" >> $LOG_FILE # 記錄狀態 if [ $HAPS -eq 0 ];then echo $START_HAPROXY >> $LOG_FILE # 記錄啓動命令 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg #啓動haproxy sleep 3 #啓動以後進行睡眠,3s後再進行判斷是否已經成功啓動,若是沒有啓動就把keepalived服務關掉,換成備份的服務 if [ `ps -C haproxy --no-header |wc -l` -eq 0 ];then echo "start haproxy failed, killall keepalived" >> $LOG_FILE killall keepalived service keepalived stop fi fi
chmod +x /etc/keepalived/haproxy_check.sh # 建立日誌目錄 mkdir /usr/local/keepalived/log
service keepalived start # 啓動 service keepalived stop # 中止 service keepalived restart # 重啓 service keepalived status # 查看keepalived狀態
# 在從1上啓動haproxy [root@localhost keepalived]# /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg # 啓動keepalived服務 [root@localhost keepalived]# service keepalived start # ip addr 查看ip能夠看到主keepalived的虛擬ip已經生效了
# 關閉主虛擬機上的keepalived,能夠看到在主虛擬機上的虛擬ip已經沒有了,同時在虛擬ip已經飄到152這臺虛擬機上了 [root@localhost keepalived]# service keepalived stop # 開啓主虛擬機上的keepalived,ip將從新回到主虛擬機上
關閉haproxy,能夠看到,keepalived把haproxy重啓了。
卸載keepalived和haproxy
卸載haproxy yum remove haproxy # 經過yum安裝的 yum remove keepalived # 經過源碼包安裝的 [root@localhost keepalived]# cd /home/keepalived-1.2.18 [root@localhost keepalived-1.2.18]# make uninstall [root@localhost keepalived-1.2.18]# cd ../ [root@localhost home]# rm -rf keepalived-1.2.18 [root@localhost home]# rm -rf keepalived-1.2.18.tar.gz [root@localhost home]# cd /etc [root@localhost etc]# rm -rf keepalived [root@localhost etc]# cd /usr/local [root@localhost local]# rm -rf keepalived [root@localhost local]# rm -rf keepalived-1.2.18/ # 驗證 [root@localhost etc]# serive keepalived satrt -bash: serive: 未找到命令 [root@localhost etc]# systemctl start keepalived Job for keepalived.service failed because the control process exited with error code. See "systemctl status keepalived.service" and "journalctl -xe" for details.
參考文章:
http://www.javashuo.com/article/p-mmxttpcn-nw.html