本文目录: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