01 背景简介

MySQL是一个小型关系型数据库,性能方面存在先天性不足,尽管如此,其也因为开源、免费、可自主迭代研发、总体拥有成本低等诸多优点被广大企业使用。目前业界有许多方法可以降低MySQL性能上限不足问题,软件层面可通过数据库中间件解决(如MyCAT、DRDS等),架构层面可以通过业务解耦、冷热温数据分离存储等方式,降低高并发业务对MySQL数据库的冲击。尽管如此,但在MySQL实例规模较多时,通过合理规划MySQL配置,一是可以确保降低高并发业务冲击数据库导致的数据库宕机风险,二是可以最大化的利用服务器资源,以节约企业资源投入成本,三是通过统一标准化的配置可以较大程度降低自动化运维研发投入成本。

本文重点针对MySQL+Keepalived高可用架构进行讲解,包含MySQL配置、Keepalived高可用配置,并附带有相应的VIP切换监控脚本。

02 实现原理

Mysql中Master->Slave的主主同步。主主是数据双向同步,主从是数据单向同步。一般情况下,主库宕机后,需要手动将连接切换到从库上。但如果使用keepalived组件架构可实现自动切换,保证数据库的高可用性。

在MySQL双主结构当中,使用keepalived,通过VIP实现Mysql双主对外连接的统一接口。即客户端通过Vip连接数据库;保障其中某一台主机出现故障,无法提供服务时,VIP可自动漂移到另一台主机上,整个过程对于客户端接来说几乎无感觉,从而实现高可用。

为保障MySQL数据的一致性,必须避免VIP频繁漂移。当keepalived检测发现MySQL服务工作异常时,VIP漂移,为禁止VIP出现二次漂移,必须人工介入操作,从而保障数据的一致性及安全性。所以,在MySQL+keepalived使用过程中,master和slave两节点均设置为backup,当人工介入,对故障主机处理完毕之后,重新启动keepalived,不会出现VIP漂移的情况,只有仅当keepalived检测到MySQL无法提供服务,才会执行VIP漂移。

03 安装实施

Mysql安装部署:

  • 软件信息

软件名称

版本号

MySQL

MySQL官方社区5.7

2aa0f8f6767e061f80a93e44fd2650b0.png

主机参数调整:

  • 禁用selinux

    #vi/etc/sysconfig/selinux
    查看是否SELINUX=disabled

  • 关闭numa
    #vi/etc/default/grub
    在GRUB_CMDLINE_LINUX这一行最后添加numa=off,使其变为GRUB_CMDLINE_LINUX=”crashkernel=auto…… rhgb quiet numa=off”,变更完成后保存退出。
    #grub2-mkconfig -o /boot/grub2/grub.cfg

  • 文件数进程数限制
    #vi /etc/security/limits.conf
    添加mysql用户限制如下:
    mysqlsoft nproc 65535
    mysql hard nproc 65535
    mysql soft nofile65536
    mysql hard nofile 65536

  • #vi/etc/sysctl.conf将该配置文件内容清空,改成以下内容
    vm.swappiness=0
    net.ipv6.conf.all.disable_ipv6=1
    net.core.somaxconn=65535
    net.core.netdev_max_backlog=65535
    net.ipv4.tcp_max_syn_backlog=65535
    net.ipv4.tcp_fin_timeout=10
    net.ipv4.tcp_tw_reuse=1
    #netipv4.tcp_tw_recycle=1
    net.core.wmem_default=87380
    net.core.wmem_max=16777216
    net.core.rmem_default=87380
    net.core.rmem_max=16777216
    net.ipv4.tcp_keepalive_time=120
    net.ipv4.tcp_keepalive_intvl=30
    net.ipv4.tcp_keepalive_probes=3
    net.ipv4.ip_local_port_range= 40000 60000
    kernel.sem = 250 32000 100 128

创建mysql用户:

#groupadd mysql

#useradd -g mysql -m mysql

依赖包安装:

软件安装前需检查以下依赖包,将缺少的依赖包安装。

#rpm-q gcc gcc-c++ zlib-devel pcre-devel readline readline-develbzip2-devel rpm-build \kernel-devel libaio-develelfutils-libelf-devel compat-libstdc++-33 compat-libcap1 cmake bisonautomake ncurses-devel xinetd openssl-devel |grep "notinstalled"

软件安装:

#cd/opt

#tar –xzvf mysql-version-os.tar.gz

#cdmysql-version-os
#cmake .-DCMAKE_INSTALL_PREFIX=/opt/mysql-version\
-DWITH_BOOST=boost/boost_1_59_0 \
-DDEFAULT_CHARSET=utf8mb4\
-DDEFAULT_COLLATION=utf8mb4_bin
# make&&makeinstall

建立软链接:

#ln-s /opt/mysql-version-os /usr/local/mysql

#ln -s/usr/local/mysql/bin/* /usr/local/bin

初始化数据库,MySQL数据目录:

实例要创建在/data/mysql下,实例中目录的具体划分如下:

主目录

二级目录

三级目录

/data/mysql/db_insname

bin(启动脚本目录)

login.sh

shutdown.sh

startup.sh

blog

mysql-bin.*

mysql-bin.index

conf(配置文件目录)

init_file.sql

insname.cnf

data(数据目录)

elog(慢日志、错误日志)

mysql.err

slow.log

mysql.pid

mysql.sock

mysql.sock.lock

nohup.out

rlog(表空间目录)

ib_logfile0

ib_logfile1

ib_logfile2

tmp(临时目录)

ulog(undo表空间目录)

undo001

undo002

配置参数说明:

参数名

数值

配置说明

max_connections

5000

数据库中已连接的所有用户总数不超过5000

max_user_connections

1200

单个用户最大连接数不超过1200

connect_timeout

10

建立数据库连接时不允许超过十秒

wait_timeout

600

状态为sleep的线程超过600秒会被关闭

max_execution_time

10000

执行时间超过10000毫秒的sql语句会被终止

innodb_lock_wait_timeout

10

事务中的DML语句10秒未获得锁,会回滚整个事务

sql_safe_updates

1

使用update或delete必须用where条件且使用索引

loose_rpl_semi_sync_master_enabled

on

开启半同步

loose_rpl_semi_sync_master_timeout

1000

客户端等待1秒得不到确认变为异步

loose_rpl_semi_sync_master_wait_for_slave_count

1

主库收到1个从库写成功则返回客户端

loose_rpl_semi_sync_master_wait_no_slave

on

启动备库后进入半同步模式

log_queries_not_using_indexes

1

查询不使用索引会计入慢日志

secure_file_priv

/data/mysql/db_insname/tmp

在库中提取数据的数据存放路径


实例创建:

setserver.ini配置文件

10.10.1.133 /usr/local/mysql /data/mysql db test1 3306 11 root 123456 512M

setServer_57.sh配置文件

#!/bin/bash

#目录、端口、实例名等信息的配置文件

INI_CFG=./setServer.ini

#IP

IP=""

#软件目录

SOFTDIR=""

#根目录

BASE_DIR=""

#实例名

INS_NAME=""

#实例名前缀

INS_NAME_PRE=""

#实例端口

INS_PORT=""

#server id

SERVER_ID=""

#实例根目录

INS_BASE_DIR=""

#管理员用户

ADMIN_USER=""

#管理员密码

ADMIN_PASSWD=""

#实例参数文件

INS_CNF=""

#初始化SQL文件

INIT_FILE=""

#INNODB_BUFFER_POOL_SIZE设定

BUFFER_POOL=""

function Isok()

{

[ $? == "0" ] && echo "Complete OK !" || echo " Failed !!!";exit 128

}

#创建实例函数

function create_instance()

{

#1、创建实例相应目录 

mkdir -p ${INS_BASE_DIR}/{bin,conf,data,rlog,ulog,blog,elog,tmp}

chmod -R 755 ${INS_BASE_DIR}

echo "****** 1、创建目录:"

echo "  启动脚本目录:${INS_BASE_DIR}/bin"

echo "  配置文件目录:${INS_BASE_DIR}/conf"

echo "  数据目录:${INS_BASE_DIR}/data"

echo "  relog目录:${INS_BASE_DIR}/rlog"

echo "  ulog目录:${INS_BASE_DIR}/ulog"

echo "  blog目录:${INS_BASE_DIR}/blog"

echo "  elog目录:${INS_BASE_DIR}/elog"

echo "  临时目录:${INS_BASE_DIR}/tmp"

#2、生成参数文件

cat <${INIT_FILE}

set global sql_safe_updates=1;

EOF

cat <${INS_CNF} 

[mysqld]

#************** basic ***************

datadir                         =${INS_BASE_DIR}/data

basedir                         =${SOFTDIR}

tmpdir                          =${INS_BASE_DIR}/tmp

secure_file_priv                =${INS_BASE_DIR}/tmp

port                            =${INS_PORT}

socket                          =${INS_BASE_DIR}/mysql.sock

pid_file                        =${INS_BASE_DIR}/mysql.pid

#************** connection ***************

max_connections                 =5000

max_connect_errors              =100000

max_user_connections            =1200

#************** sql timeout & limits ***************

max_execution_time              =10000

group_concat_max_len            =1048576

lock_wait_timeout               =60

#autocommit                      =0

lower_case_table_names          =1

thread_cache_size               =64

disabled_storage_engines        ="MyISAM,FEDERATED"

character_set_server            =utf8

transaction-isolation           ="READ-COMMITTED"

skip_name_resolve               =ON

explicit_defaults_for_timestamp =ON

log_timestamps                  =SYSTEM

local_infile                    =OFF

event_scheduler                 =OFF

query_cache_type                =OFF

query_cache_size                =0

lc_messages                     =en_US

lc_messages_dir                 =${SOFTDIR}/share

init_connect                    ="set names utf8"

#sql_mode                        =NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO

init_file                       =${INIT_FILE}

#init_slave

#******************* err & slow & general ***************

log_error                       =${INS_BASE_DIR}/elog/mysql.err

#log_output                      ="TABLE,FILE"

slow_query_log                  =ON

slow_query_log_file             =${INS_BASE_DIR}/elog/slow.log

long_query_time                 =1

log_queries_not_using_indexes   =0

log_throttle_queries_not_using_indexes = 10

general_log                     =OFF

general_log_file                =${INS_BASE_DIR}/elog/general.log

#************** binlog & relaylog ***************

expire_logs_days                =7

sync_binlog                     =1

log-bin                         =${INS_BASE_DIR}/blog/mysql-bin

log-bin-index                   =${INS_BASE_DIR}/blog/mysql-bin.index

max_binlog_size                 =500M

binlog_format                   =ROW

binlog_rows_query_log_events    =ON

binlog_cache_size               =2M

binlog_stmt_cache_size          =2M

max_binlog_cache_size           =512M

max_binlog_stmt_cache_size      =512M

relay_log                       =${INS_BASE_DIR}/blog/relay

relay_log_index                 =${INS_BASE_DIR}/blog/relay.index

max_relay_log_size              =500M

relay_log_purge                 =ON

relay_log_recovery              =ON

#*************** rpl_semi_sync ***************

loose_rpl_semi_sync_master_enabled                =ON

loose_rpl_semi_sync_master_timeout                =1000

loose_rpl_semi_sync_master_trace_level            =32

loose_rpl_semi_sync_master_wait_for_slave_count   =1

loose_rpl_semi_sync_master_wait_no_slave          =ON

loose_rpl_semi_sync_master_wait_point             =AFTER_SYNC

loose_rpl_semi_sync_slave_enabled                 =ON

loose_rpl_semi_sync_slave_trace_level             =32

#*************** group commit ***************

binlog_group_commit_sync_delay              =1

binlog_group_commit_sync_no_delay_count     =1000

#*************** gtid ***************

gtid_mode                       =ON

enforce_gtid_consistency        =ON

master_verify_checksum          =ON

sync_master_info                =1

#*************slave ***************

skip-slave-start                =1

#read_only                      =ON

#super_read_only                =ON

log_slave_updates               =ON

server_id                       =${SERVER_ID}

report_host                     =$IP

report_port                     =${INS_PORT}

slave_load_tmpdir               =${INS_BASE_DIR}/tmp

slave_sql_verify_checksum       =ON

slave_preserve_commit_order     =1

#*************** muti thread slave ***************

slave_parallel_type                         =LOGICAL_CLOCK

slave_parallel_workers                      =4

master_info_repository                      =TABLE

relay_log_info_repository                   =TABLE

#*************** buffer & timeout ***************

read_buffer_size                =1M

read_rnd_buffer_size            =2M

sort_buffer_size                =1M

join_buffer_size                =1M

tmp_table_size                  =16777216

max_allowed_packet              =64M

max_heap_table_size             =64M

connect_timeout                 =10

wait_timeout                    =600

interactive_timeout             =600

net_read_timeout                =30

net_write_timeout               =30

#*********** myisam ***************

skip_external_locking           =ON

key_buffer_size                 =2M

bulk_insert_buffer_size         =16M

concurrent_insert               =ALWAYS

open_files_limit                =65000

table_open_cache                =16000

table_definition_cache          =16000

#*********** innodb ***************

default_storage_engine              =InnoDB

default_tmp_storage_engine          =InnoDB

internal_tmp_disk_storage_engine    =InnoDB

innodb_data_home_dir                =${INS_BASE_DIR}/data

innodb_log_group_home_dir           =${INS_BASE_DIR}/rlog

innodb_log_file_size                =1024M

innodb_log_files_in_group           =3

innodb_undo_directory               =${INS_BASE_DIR}/ulog

innodb_undo_log_truncate            =on  

innodb_max_undo_log_size            =1024M

innodb_undo_tablespaces             =3

innodb_flush_log_at_trx_commit      =2

innodb_fast_shutdown                =1

innodb_flush_method                 =O_DIRECT

innodb_io_capacity                  =1000

innodb_io_capacity_max              =4000

innodb_buffer_pool_size             =${BUFFER_POOL}

innodb_log_buffer_size              =8M

innodb_autoinc_lock_mode            =1

innodb_buffer_pool_load_at_startup  =ON

innodb_buffer_pool_dump_at_shutdown =ON

innodb_buffer_pool_dump_pct         =15

innodb_max_dirty_pages_pct          =85

innodb_lock_wait_timeout            =10

#innodb_locks_unsafe_for_binlog      =1

innodb_old_blocks_time              =1000

innodb_open_files                   =63000

innodb_page_cleaners                =4

innodb_strict_mode                  =ON

innodb_thread_concurrency           =0

innodb_sort_buffer_size             =64M

innodb_print_all_deadlocks          =1

innodb_rollback_on_timeout          =ON

EOF

echo "****** 2、生成参数文件:"

echo "  实例${INS_NAME}的参数文件: ${INS_CNF}"

# 3、实例化数据库

echo "****** 3、初始化数据库:"

#[ `echo $USER` == "root" ] && chown mysql:root $INS_BASE_DIR

${SOFTDIR}/bin/mysqld --defaults-file=${INS_CNF} \

--initialize-insecure --user=mysql \

--basedir=${SOFTDIR} \

--datadir=${INS_BASE_DIR}/data

#4、生成启动、关闭、登陆脚本

echo "****** 4、生成启动、关闭、登陆脚本:"

cat <${INS_BASE_DIR}/bin/startup.sh

#!/bin/bash

source /etc/profile

source ~/.bash_profile

export UMASK=0644

export UMASK_DIR=0750

## vars

SOFTDIR=${SOFTDIR}

DBHOME=${INS_BASE_DIR}

DBNAME=${INS_NAME}

CNF=\${DBHOME}/conf/\${DBNAME}.cnf

DATADIR=\${DBHOME}/data

## startup

nohup \${SOFTDIR}/bin/mysqld_safe --defaults-file=\${CNF} --ledir=\${SOFTDIR}/bin >\${DBHOME}/nohup.out 2>&1 &

EOF

cat <${INS_BASE_DIR}/bin/shutdown.sh

#!/bin/bash

source /etc/profile

source ~/.bash_profile

## vars

SOFTDIR=${SOFTDIR}

DBHOME=${INS_BASE_DIR}

DBNAME=${INS_NAME}

CNF=\${DBHOME}/conf/\${DBNAME}.cnf

SOCK=\${DBHOME}/mysql.sock

## shutdown

\${SOFTDIR}/bin/mysqladmin --defaults-file=\${CNF} -uroot -p -S\${SOCK} shutdown

EOF

cat <${INS_BASE_DIR}/bin/login.sh

SOFTDIR=${SOFTDIR}

DBHOME=${INS_BASE_DIR}

DBNAME=${INS_NAME}

SOCK=\${DBHOME}/mysql.sock

\${SOFTDIR}/bin/mysql -uroot -p -S\${SOCK} -A

EOF

chmod 700 ${INS_BASE_DIR}/bin/startup.sh ${INS_BASE_DIR}/bin/shutdown.sh ${INS_BASE_DIR}/bin/login.sh

#5、修改管理员密码

echo "****** 5、修改管理员密码:"

hostname=`hostname`

sh ${INS_BASE_DIR}/bin/startup.sh

sleep 30

${SOFTDIR}/bin/mysql -uroot -S${INS_BASE_DIR}/mysql.sock<

#install semi sync

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

install plugin rpl_semi_sync_master soname 'semisync_master.so';

#root

alter user 'root'@'localhost' identified by "${ADMIN_PASSWD}";

delete from mysql.user where user='root' and host=lower("${hostname}");

#备份用户

GRANT SELECT,SHOW VIEW,TRIGGER,LOCK TABLES,RELOAD,PROCESS,SUPER ON *.* TO 'bkpuser'@'%' IDENTIFIED BY "n#CJ^f&i";    

#复制用户

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replic'@'%' IDENTIFIED BY "4%REplic";

#业务数据监控用户

create user monitorjk identified by 'esEYq7QWkB6F2M$';

#数据库监控用户

grant PROCESS, REPLICATION CLIENT, SELECT on *.* to zabbixjk identified by 'CvNYz!6WIb9u';

#4A用户

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER, SHOW DATABASES, CREATE USER ,RELOAD ON *.* TO aiuap@'%' IDENTIFIED BY "p#1nVF.|c1" WITH GRANT option;

#运维管理用户

GRANT ALL ON *.* TO myrobot@'127.0.0.1' identified by 'Si*hx79*HIqHQdLY' with grant option;

#inception用户

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, PROCESS, INDEX, ALTER, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, TRIGGER ON *.* TO inception identified by 'fF&w@tw5qZK1WRvi';

flush privileges;

shutdown;

EOF

[ $? == "0" ] && echo " 密码修改成功!"

#修改配置文件,使半同步参数生效

sleep 5

sed -i 's/loose_//g' ${INS_CNF}

sh ${INS_BASE_DIR}/bin/startup.sh

echo "****** 6、网络监听:"

netstat -pltn 2>/dev/null |grep -E "Proto|$INS_PORT|mysql"

echo "****** 7、MySQL错误日志:"

grep -Ei "error|warning" $INS_BASE_DIR/elog/mysql.err

}

if [ -f ${INI_CFG} ]; then

 grep -v "^#" ${INI_CFG} | while read line

 do

          IP=`echo ${line} | cut -d" " -f1`

          SOFTDIR=`echo ${line} | cut -d" " -f2 | sed 's/\/$//'`

          BASE_DIR=`echo ${line} | cut -d" " -f3 | sed 's/\/$//'`

          INS_NAME_PRE=`echo ${line} | cut -d" " -f4`

          INS_NAME=`echo ${line} | cut -d" " -f5`

          INS_PORT=`echo ${line} | cut -d" " -f6`

          SERVER_ID=`echo ${line} | cut -d" " -f7`

          ADMIN_USER=`echo ${line} | cut -d" " -f8`

          ADMIN_PASSWD=`echo ${line} | cut -d" " -f9`

  BUFFER_POOL=`echo ${line} | cut -d" " -f10`

          INS_BASE_DIR=${BASE_DIR}/${INS_NAME_PRE}_${INS_NAME}

          INS_CNF=${INS_BASE_DIR}/conf/${INS_NAME}.cnf

  INIT_FILE=${INS_BASE_DIR}/conf/init_file.sql

          echo "****** 实例${INS_NAME}信息: ******"

          echo "        IP: ${IP}"

          echo "        软件目录: ${SOFTDIR}"

          echo "        根目录: ${BASE_DIR}"

          echo "        实例根目录: ${INS_BASE_DIR}"

          echo "        实例名前缀: ${INS_NAME_PRE}"

          echo "        实例名: ${INS_NAME}"

          echo "        实例端口: ${INS_PORT}"

          echo "        server_id: ${SERVER_ID}"

          echo "        管理员用户: ${ADMIN_USER}"

          echo "        管理员密码: ${ADMIN_PASSWD}"

  echo "        INNODB_BUFFER_POOL_SIZE设定: ${BUFFER_POOL}"

          if [ `echo ${line} | awk '{print NF}'` != "10" ]; then

              echo "ERROR:创建实例相应参数不够!"

        echo "##############################################################################################"

                  echo -e "\n"

          #判断端口与ibdata01文件是否存在,都不存在则创建实例。存在一个则创建失败

          elif [ X"`netstat -ltn | grep ${INS_PORT}`" = X"" ] && [ ! -f ${INS_BASE_DIR}/data/ibdata01 ]; then

          #调用创建实例函数

          create_instance;

       else

         echo "ERROR:端口${INS_PORT}或${INS_BASE_DIR}/data/ibdata01文件存在,创建实例失败!"

         echo "##############################################################################################"

                   echo -e "\n"

   fi

done

else

 echo "ERROR:${INI_CFG}配置文件不存在!"

 exit 1

fi

数据库的初始化使用上面两个脚本完成。

  • 1.填写setserver.ini配置文件。

  • 2.执行setserver.sh,初使化数据库。

setserver.ini,填写方法如下:

序列

名称

示例

第1列

ip

0.0.0.1

第2列

软件目录

/usr/local/mysql

第3列

数据根目录

/data/mysql

第4列

实例名前缀

Db

第5列

实例名

Insname

第6列

端口

20001

第7列

serverid(如果有两个节点,serverid不能一样,一个写01一个写02)

port+01/port+02

第8列

root账号

Root

第9列

root密码

Root

setserver.sh

用mysql用户执行脚本完成数据库实例初始化。

登录数据库

数据库登录脚本在/data/mysql/db_InsName/bin下,login.sh。

04 主主复制

复制方式:半同步、主主复制

操作步骤:

登陆节点1:

步骤

操作

解释

1

mysql>RESET MASTER;

重置

2

mysql>CHANGE MASTER TO
MASTER_HOST='HOSTIP2',
MASTER_USER='replicuser',
MASTER_PASSWD='passwd',
MASTER_PORT='PORT',
MASTER_AUTO_POSITION=1;

配置主主

3

mysql>START SLAVE;

启动服务

登陆节点2:

步骤

操作

解释

1

mysql>RESET MASTER;

重置

2

mysql>CHANGE MASTER TO
MASTER_HOST='HOSTIP1',
MASTER_USER='replicuser',
MASTER_PASSWD='passwd',
MASTER_PORT='PORT',
MASTER_AUTO_POSITION=1;

配置主主

3

mysql>START SLAVE;

启动服务

05 集群部署规范

集群中的每一个MySQL实例都单独部署在一个物理机,考虑到容错和网络环境尽量实现跨机柜部署。


禁止集群的一对主从部署在同一台物理机。
MySQL不应和高磁盘I/O,高计算任务的应用部署在同一台物理机上

07 Keepalived安装部署

软件名称

版本号

Keepalived

Keepalived-1.3.2

安装目录规范:

软件安装目录:/usr/local/keepalived

日志输出目录:/usr/local/keepalived/log/keepalived.log

配置文件目录:/etc/keepalived/keepalived.conf

检测脚本目录:/etc/keepalived/scripts/

参数文件目录:/etc/sysconfig/keepalived

执行文件目录:/usr/sbin/keepalived

启动文件目录:/etc/rc.d/init.d/keepalived

源码存放目录:/tmp/keepalived-1.3.2/

keepalived安装:

检测依赖包:

在root用户权限下执行:

rpm-qa make gcc libpopt-dev libnl-dev libcurl4-openssl-dev | grep "notinstall"

查看是否存在未安装的依赖包。(注意:当操作系统语言为中文时需注意,notinstall筛选不出结果,可自行查看是否存在对应依赖包。)

如果存在未安装的依赖包,则对缺失的依赖包进行安装。

解压缩编译:

tar zxf keepalived-1.3.2.tar.gz,进入目录并编译

在编译过程中,只需要执行安装目录,其他使用默认配置即可。

./configure –prefix=/usr/local/keepalived

make && make install

所需文件创建:

在keepalived1.3.2中,部分系统所需使用的脚本文件在源码安装包中,即脚本存在位置为:/tmp/keepalived-1.3.2/keepalived/etc。

复制可执行文件:

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

复制系统服务文件:

cp/tmp/keepalived-1.3.2/keepalived/etc/init.d/keepalived  /etc/rc.d/init.d/

复制参数文件:

cp/usr/local/keepalived/etc/sysconfig/keepalived  /etc/sysconfig/

创建配置文件/脚本文件目录:

mkdir -p /etc/keepalived/scripts

     修改文件目录权限:

将以下目录用户及所属组该为mysql

/etc/keepalived

/usr/local/keepalived

chown -R mysql:mysql /etc/keepalived

chown -R mysql:mysql /usr/local/keepalived

     修改日志输出:

1、修改keepalived启动参数文件

vi /etc/sysconfig/keepalvied

将文件中KEEPALIVED_OPTIONS=”-D”修改为:

KEEPALIVED_OPTIONS=”-D -d -S 0”

2、修改rsyslog.conf文件

vi /etc/rsyslog.conf

在文件最后增加一行:

local0.* /usr/local/keepalived/log/keepalived.log

3、重启rsyslog服务

systemctl restart rsyslog

      配置keepalived:

      keepalived配置文件及说明

      参数说明:

参数名

配置说明

vrrp_script块

keepalived调用检测脚本块

script

检测脚本文件指定

ineerval

检测脚本调用周期

vrrp_instance块

keepalivd配置块

state

keepalived角色状态,只有MASTER和BACKUP两种,必须使用大写

interface

keepalived实例绑定网卡

virtual_router_id

实例ID,用于主备之间互通,主备必须相同,值范围:0-255

priority

权重值

advert_int

keepalived之间心跳检测时间间隔

nopreempt

设置不抢占

track_script

选择检测脚本块

authentication

认证设置

auth_type

认证方式

auth_pass

认证密码,最大不可超过8位

virtual_ipaddress

设置服务IP

vrrp_garp_master_refresh

Master发一次ARP包到网关的间隔时间,可以防止产生脑裂

配置文件展示:

global_defs {

vrrp_garp_master_refresh10  #Master间隔10s发一次ARP包到网关

}

vrrp_scriptcheck_run {

script"/etc/keepalived/scripts/keepalived_check_mysql.sh"#

需手工修改文件中的mysql端口号

interval30

weight0

}

vrrp_instanceVI_1 {

stateBACKUP

interfaceteam0        # 网卡,根据实际情况填写

virtual_router_id155  # 推荐使用虚IP第四段数字

priority101

advert_int1

authentication{

auth_typePASS

auth_pass1111

}

virtual_ipaddress{

0.0.0.1     # 虚IP

}

track_script{

check_run

}

notify_master/etc/keepalived/scripts/notify_master.sh

}

Keepalived手动切换操作方案

mysql数据库VIP切换操作步骤

序号

主任务

子任务

操作节点

操作命令

1

VIP切换前准备

检查数据库同步状态

主从节点

show slave status\G

2

检查数据库日志

主从节点

tail -1000f  /data/db_{实例名}/elog/mysql.err

3

检查keepalived状态

主从节点

ps -ef |grep -i keepalived

4

VIP切换阶段

设置read_only为on

主节点

set global read_only=on;

5

kill应用连接

主节点

kill processid;

6

切换VIP

主节点

sudo systemctl stop keepalived

7

检查VIP是否切换成功

主从节点

ip a

8

检查应用连接

主从节点

show processlist;

9

检查同步状态

主从节点

show slave status\G

10

设置read_onlyoff

新主节点

set global read_only=off;

说明:为保障MySQL数据库数据的一致性,防止keepalived虚拟IP节点漂移次数过于频繁,在state中设置为双BACKUP,即主从均为BACKUP,此时,如果主机出现故障或宕机,从机检测到之后,接管VIP,并继续提供服务。主机恢复,仍不会争用VIP,直至下次从机出现故障宕机,VIP才会进行第二次漂移,恢复到原主机,继续提供服务。该设置避免频繁切换数据库节点,导致数据的不一致。

08 小结

当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服务,而且切换的时间非常短,mysql双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备,但是一个Master宕机后不能实现动态切换。使用Keepalived,可以通过虚拟IP,实现双主对外的统一接口以及自动检查、失败切换机制,基本不需要人工干预操作,从而实现MySQL数据库的高可用性。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐