zoukankan      html  css  js  c++  java
  • mycat详解

    本文目录:

    1.安装mycat

    2.mycat全局表

    3.mycat读写分离

    4.mycat分片规则

    5.E-R表

    6.HAProxy

    7.mycat负载均衡集群

    8.Keepalived

    1.安装mycat

    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的数据已经插入进去了:

    2.mycat全局表

    1.全局表的概念

    在项目中,总会一部分字典项等数据,这种数据一般数据量不会很大,而且改动也比较少。在mycat中将这种表称之为全局表,通常这种表可以不需要进行拆分,每个分片都创建一张相同的表,在所有的分片上都保存一份数据。在进行插入、更新、删除的时候,会将sql语句发送到所有的分片上执行,在进行查询时,也会把sql发送到各个分片上。这样避免了跨库的关联操作,直接与本分片上的全局表进行聚合操作。

    2.全局表的特征

    1. 插入、更新操作会实时在所有的节点上执行,保持各分片的数据一致性
    2. 查询时,只从一个节点获取
    3. 可以跟任何一个表进行jion操作

    3.全局表测试

    1.打开数据库主从并在主库中创建数据库/表

    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;
    

    2.配置schema.xml,配置上一步创建的表

    ​ 在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" />
    

    3.将schema.xml并上传到服务器中,并查看没有问题

    4.启动mycat并插入测试数据

    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)
    

    3.mycat读写分离

    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是主库,151、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)
    

    4.mycat分片规则

    ​ 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则插入到默认节点里。

    5.E-R表

    由于mycat底层不支持跨分片操作,如果需求中有多个相关的分片表进行关联操作时,就需要如E-R分片的配置逻辑。 基于E-R关系进行分片,子表的记录与其父表的记录保存在同一个分片上,这样关联就不需要跨库进行查询了。

    1.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. 原理一样.

    2.E-R表插入数据

    # 启动后,创建表
    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');
    

    3.E-R表测试

    如下图所示:使用navicat查询, 基于E-R关系进行分片,子表的记录与其父表的记录保存在同一个分片上,这样关联就不需要跨库进行查询了。

    6.HAProxy

    笔者使用的环境:

    服务器名称 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

    1.HAProxy介绍

    1. HAProxy 是一款提供高可用性、负载均衡以及基于TCP和HTTP应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。
    2. HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。
    3. HAProxy支持连接拒绝 : 因为维护一个连接的打开的开销是很低的,有时我们很需要限制攻击爬虫,也就是说限制它们的连接打开从而限制它们的危害。
    4. HAProxy 支持全透明代理:可以用客户端IP地址或者任何其他地址来连接后端服务器。这个特性仅在Linux 2.4/2.6内核打了cttproxy补丁后才可以使用.

    2. HAProxy特性

    1. 可靠性与稳定性都非常出色,可与硬件级设备媲美
    2. 支持连接拒绝,可以用于防止DoS攻击
    3. 支持长连接、短连接和日志功能,可根据需要灵活配置
    4. 路由 HTTP 请求到后端服务器,基于cookie作会话绑定;同时支持通过获取指定的 url 来检测后端服务器的状态
    5. HAProxy 还拥有功能强大的 ACL 支持,可灵活配置路由功能,实现动静分离,在架构设计与实现上带来很大方便
    6. 可支持四层和七层负载均衡,几乎能为所有服务常见的提供负载均衡功能
    7. 拥有功能强大的后端服务器的状态监控 web 页面,可以实时了解设备的运行状态 ,还可实现设备上下线等简单操作。
    8. 支持多种负载均衡调度算法,并且也支持 session 保持。
    9. Haproxy 七层负载均衡模式下,负载均衡与客户端及后端的服务器会分别建立一次TCP连接,而在四层负载均衡模式下(DR),仅建立一次 TCP 连接;七层负载均衡对负载均衡设备的要求更高,处理能力也低于四层负载均衡

    3.HAProxy安装

    ​ HAProxy的安装非常简单:yum install -y haproxy

    ​ 查看安装的haproxy: rpm -qi haproxy

    ​ 安装完成后的目录:cd /usr/sbin

    ​ 配置文件的目录:cd /etc/haproxy/

    4.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(2次正确表示服务器可用) fall 3(3次失败表示服务器不可用)
    

    5.启动haproxy负载均衡器

    /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.mycat负载均衡集群

    1.静态负载均衡算法包括:轮询,比率,优先权

    ​ 轮询:顺序循环将请求依次顺序循环地连接每个服务器。当其中某个服务器发生第二到第7层的故障,BIG-IP就把其从顺序循环队列中拿出,不参加下一次的轮询,直到其恢复正常。
    ​ 比率:给每个服务器分配一个加权值为比例,根椐这个比例,把用户的请求分配到每个服务器。当其中某个服务器发生第二到第7层的故障,BIG-IP 就把其从服务器队列中拿出,不参加下一次的用户请求的分配, 直到其恢复正常。
    ​ 优先权:给所有服务器分组,给每个组定义优先权,BIG-IP 用户的请求,分配给优先级最高的服务器组;当最高优先级中所有服务器出现故障,BIG-IP 才将请求送给次优先级的服务器组。这种方式,实际为用户提供一种热备份的方式。

    2.负载均衡的优势

    ​ (1)高性能:负载均衡技术将业务较均衡的分担到多台设备或链路上,从而提高了整个系统的性能;
    ​ (2)可扩展性:负载均衡技术可以方便的增加集群中设备或链路的数量,在不降低业务质量的前提下满足不断增长的业务需求;
    ​ (3)高可靠性:单个甚至多个设备或链路出现故障也不会导致业务中断,提高了整个系统的可靠性;
    ​ (4)可管理性:大量的管理共组都集中在使用负载均衡技术的设备上,设备集群或链路集群只需要维护通过的配置即可;
    ​ (5)透明性:对用户而言,集群等于一个或多个高可靠性、高性能的设备或链路,用户感知不到,也不关心具体的网络结构,增加或减少设备或链路数量都不会影响正常的业务。

    8.keepalived

    1.keepalived概念

    ​ keepalived,保持存活,就是高可用设备或热备用来防止单点故障的发生,keepalived通过请求一个vip来达到请求真实ipi地址的功能,而vip能够在一台机器发生故障的时候,自动漂移到另外一台机器上,从来达到了高可用HAProxy的功能。

    2.keepalived的功能

    • 通过ip漂移
    • 对HAProxy应用层的应用服务器集群进行状态监控

    3.keepalived原理

    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 状态。

    4.keepalived组件

    keepalived是模块化设计,不同模块负责不同的功能,core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。checkers负责健康检查,包括常见的各种检查方式。VRRP模块是来实现VRRP协议的。

    5.keepalived配置

    1.解压并安装(安装keepalived 需要用到 openssl):

    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
    

    2.将keepalived安装成Linux服务

    # 因为没有使用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
    

    3.keepalived配置文件

    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
          }
    }
    
    
    

    4.keepalived检测脚本

    #!/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
    

    5.给脚本赋值权限

    chmod +x /etc/keepalived/haproxy_check.sh
    # 创建日志目录
    mkdir /usr/local/keepalived/log
    

    6.keepalived相关程序:

    service keepalived start # 启动
    service keepalived stop  # 停止
    service keepalived restart # 重启
    service keepalived status	# 查看keepalived状态
    

    7.演示ip漂移

    # 在从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将重新回到主虚拟机上
    

    8.演示Keepalived 重新启动haproxy

    关闭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.
    
    

    参考文章:

    https://www.cnblogs.com/z-qinfeng/p/9726707.html

    https://blog.csdn.net/bbwangj/article/details/82763431

    https://blog.csdn.net/l1028386804/article/details/76397064

  • 相关阅读:
    LeetCode翻转矩阵后的得分-Python3<六>
    LeetCode子域名访问计数-Python3.7<五>
    LeetCode 键盘行-Python3.7<四>
    流程控制<二>
    Numbers、Strings、Lists 笔记<一>
    LeetCode-数组操作-Python<三>
    LeetCode链表相加-Python<二>
    LeetCode两数之和-Python<一>
    使用Django创建网站项目<二>
    Windows下vue-cli脚手架搭建入门<一>
  • 原文地址:https://www.cnblogs.com/pluto-charon/p/14047875.html
Copyright © 2011-2022 走看看