架构图
故障转移过程
(1)从宕机崩溃的master保存二进制日志事件(binlog events);
(2)识别含有最新更新的slave;
(3)应用差异的中继日志(relay log)到其他的slave;
(4)应用从master保存的二进制日志事件(binlog events);
(5)提升一个slave为新的master;
(6)使其他的slave连接新的master进行复制;
(7)在新的master启动vip地址,保证前端请求可以发送到新的master。
介绍
MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA 由两部分组成;
- MHA Manager(管理节点)
MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。
- MHA Node(数据节点)
MHA Node运行在每台MySQL服务器上
MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。
目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器。
缺陷
- 至少需要三台服务器 - 一主二从,即一台充当master,一台充当备用master,另外一台充当从库
- 依赖 ssh 通信 - 在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。
配置方法
基于 Docker
服务器配置
- 操作系统:Ubuntu 14.04
- mha-manager - 172.17.0.2
- mha_master - 172.17.0.3
- mha_slave01(主备) - 172.17.0.4
- mha_slave02 - 172.17.0.5
1. MySQL 主从复制
2. MHA 配置
-
安装 MHA
- MHA 有 manager 端和 node 端,这是下载地址:MHA
- mha-manager 安装 manager(mha4mysql-manager_0.55-0_all.deb) 端和 node(mha4mysql-node_0.54-0_all.deb) 端
- mha_master、mha_slave01、mha_slave02 安装 node(mha4mysql-node-0.56.tar.gz) 端
以下是执行的命令:
mha-manager(172.17.0.2)-
下载安装包,解压
root@mha-manager:~# wget https://downloads.mariadb.com/MHA/mha4mysql-manager-0.56.tar.gz root@mha-manager:~# wget https://downloads.mariadb.com/MHA/mha4mysql-node-0.56.tar.gz root@mha-manager:~# tar -xzvf mha4mysql-node-0.56.tar.gz root@mha-manager:~# tar -xzvf mha4mysql-manager-0.56.tar.gz
-
首先安装 MHA Node
root@mha-manager:~/mha4mysql-node-0.56# cd mha4mysql-node-0.56 root@mha-manager:~/mha4mysql-node-0.56# perl Makefile.PL root@mha-manager:~/mha4mysql-node-0.56# make && make install
如果在执行
perl Makefile.PL
命令时,出现如下输出:[Core Features] - DBI ...missing. - DBD::mysql ...missing. ==> Auto-install the 2 mandatory module(s) from CPAN? [y] y
并且在执行
make
命令时出现如下输出:[ERROR] Expected to read at least 204133 lines, but /root/.cpanplus/02packages.details.txt.gz contains only 190253 lines! *** Installing DBI... *** Could not find a version 0 or above for DBI; skipping. *** Installing DBD::mysql... *** Could not find a version 0 or above for DBD::mysql; skipping. *** Module::AutoInstall installation finished.
需要手动安装 libdbd-mysql-perl
root@mha-manager:~/mha4mysql-node-0.56# apt install libdbd-mysql-perl
重新执行
make && make install
-
安装 MHA Manager
root@mha-manager:~# cd mha4mysql-manager-0.56 root@mha-manager:~/mha4mysql-manager-0.56# perl Makefile.PL
会输出如下信息:
*** Module::AutoInstall version 1.03 *** Checking for Perl dependencies... [Core Features] - DBI ...loaded. (1.63) - DBD::mysql ...loaded. (4.025) - Time::HiRes ...loaded. (1.9725) - Config::Tiny ...missing. - Log::Dispatch ...missing. - Parallel::ForkManager ...missing. - MHA::NodeConst ...loaded. (0.56) ==> Auto-install the 3 mandatory module(s) from CPAN? [y]
先结束运行,安装依赖包
root@mha-manager:~/mha4mysql-manager-0.56# apt install libconfig-tiny-perl root@mha-manager:~/mha4mysql-manager-0.56# apt install liblog-dispatch-perl root@mha-manager:~/mha4mysql-manager-0.56# apt install libparallel-forkmanager-perl
安装完成后重新执行
perl Makefile.PL
,输出如下:*** Module::AutoInstall version 1.03 *** Checking for Perl dependencies... [Core Features] - DBI ...loaded. (1.63) - DBD::mysql ...loaded. (4.025) - Time::HiRes ...loaded. (1.9725) - Config::Tiny ...loaded. (2.20) - Log::Dispatch ...loaded. (2.41) - Parallel::ForkManager ...loaded. (1.06) - MHA::NodeConst ...loaded. (0.56) *** Module::AutoInstall configuration finished. Checking if your kit is complete... Looks good Writing Makefile for mha4mysql::manager Writing MYMETA.yml and MYMETA.json
然后执行
root@mha-manager:~/mha4mysql-manager-0.56# make && make install
就很顺利了。
安装完成后会产生一些相关工具:
Manager 工具
masterha_check_ssh : 检查MHA的SSH配置。 masterha_check_repl : 检查MySQL复制。 masterha_manager : 启动MHA。 masterha_check_status : 检测当前MHA运行状态。 masterha_master_monitor : 监测master是否宕机。 masterha_master_switch : 控制故障转移(自动或手动)。 masterha_conf_host : 添加或删除配置的server信息。
Node 工具
save_binary_logs : 保存和复制master的二进制日志。 apply_diff_relay_logs : 识别差异的中继日志事件并应用于其它slave。 filter_mysqlbinlog : 去除不必要的ROLLBACK事件(MHA已不再使用这个工具)。 purge_relay_logs : 清除中继日志(不会阻塞SQL线程)。
Node 工具通常由MHA Manager的脚本触发,无需人为操作。
注意:为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL 5.5的半同步复制。关于半同步复制原理各位自己进行查阅。(不是必须)
-
安装 MHA Node
mha_master mha_slave01 mha_slave02
root@mha_master:~# cd mha4mysql-node-0.56 root@mha_master:~/mha4mysql-node-0.56# apt install libdbd-mysql-perl root@mha_master:~/mha4mysql-node-0.56# perl Makefile.PL root@mha_master:~/mha4mysql-node-0.56# make && make install
三台机器安装完毕后就可以开始接下来的配置了。
-
配置 MHA
-
配置四台机器之间 ssh 互相免密钥登陆
-
用ssh-keygen创建公钥,一直默认回车,最后会在.ssh/下面生成id_rsa.pub
root@mha-manager:~# ssh-keygen -t rsa
复制
id_rsa.pub
里面的内容粘贴到另外三台机器的/root/.ssh/authorized_keys
中,如果文件不存在的话新建一个即可。同理,在另外三台机器上进行同样的操作,让这四台机器之间可以无密码登录。
如果是 root 登录的话,需要修改 ssh 配置文件,
vi /etc/ssh/sshd_config
中的 PermitRootLogin ,设置为 YES,再重启 ssh。
-
-
配置 MHA Manager
-
创建数据文件目录和配置文件目录
root@mha-manager:~# pwd /root root@mha-manager:~# mkdir -p /usr/local/masterha/app1 root@mha-manager:~# mkdir /etc/masterha root@mha-manager:~# cp mha4mysql-manager-0.56/samples/conf/app1.cnf /etc/masterha/
-
MHA 的配置文件
[server default] manager_workdir=/var/log/masterha/app1 manager_log=/var/log/masterha/app1/manager.log master_binlog_dir=/var/lib/mysql # master_ip_failover_script=/data/perl/master_ip_failover # master_ip_online_change_script=/data/perl/master_ip_failover # report_script=/data/perl/send_report user=root password=root remote_workdir=/tmp repl_user=repl_user repl_password=123456 ssh_user=root [server1] hostname=172.17.0.3 port=3306 [server2] hostname=172.17.0.4 port=3306 candidate_master=1 check_repl_delay=0 [server3] hostname=172.17.0.5 port=3306
参数解读:
参数信息 参数含义 备注 manager_workdir 设置manager的工作目录 $1 manager_log 设置manager的日志 $1 master_binlog_dir 设置master 保存binlog的位置,以便MHA可以找到master的日志 $1 master_ip_failover_script 设置自动failover时候的切换脚本 $1 master_ip_online_change_script 设置手动切换时候的切换脚本 $1 password 设置mysql中root用户的密码 $1 user 设置监控用户root $1 ping_interval 设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover $1 remote_workdir 设置远端mysql在发生切换时binlog的保存位置 $1 repl_password 设置复制用户的密码 $1 repl_user 设置复制环境中的复制用户名 $1 report_script 设置发生切换后发送的报警的脚本 $1 shutdown_script 设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用) $1 ssh_user 设置ssh的登录用户名 $1 hostname 主机名/IP $1 port 端口号 $1 candidate_master 设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave $1 check_repl_delay 默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master $1
-
-
环境测试
-
检查 MHA Manager 到所有 MHA Node 的 ssh 连接状态
root@mha-manager:~# masterha_check_ssh --conf=/etc/masterha/app1.cnf Sat Nov 4 05:30:41 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Sat Nov 4 05:30:41 2017 - [info] Reading application default configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:30:41 2017 - [info] Reading server configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:30:41 2017 - [info] Starting SSH connection tests.. Sat Nov 4 05:30:43 2017 - [debug] Sat Nov 4 05:30:42 2017 - [debug] Connecting via SSH from root@172.17.0.4(172.17.0.4:22) to root@172.17.0.3(172.17.0.3:22).. Warning: Permanently added '172.17.0.4' (ECDSA) to the list of known hosts. Warning: Permanently added '172.17.0.3' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:43 2017 - [debug] ok. Sat Nov 4 05:30:43 2017 - [debug] Connecting via SSH from root@172.17.0.4(172.17.0.4:22) to root@172.17.0.5(172.17.0.5:22).. Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:43 2017 - [debug] ok. Sat Nov 4 05:30:44 2017 - [debug] Sat Nov 4 05:30:41 2017 - [debug] Connecting via SSH from root@172.17.0.3(172.17.0.3:22) to root@172.17.0.4(172.17.0.4:22).. Warning: Permanently added '172.17.0.3' (ECDSA) to the list of known hosts. Warning: Permanently added '172.17.0.4' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:43 2017 - [debug] ok. Sat Nov 4 05:30:43 2017 - [debug] Connecting via SSH from root@172.17.0.3(172.17.0.3:22) to root@172.17.0.5(172.17.0.5:22).. Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:44 2017 - [debug] ok. Sat Nov 4 05:30:44 2017 - [debug] Sat Nov 4 05:30:43 2017 - [debug] Connecting via SSH from root@172.17.0.5(172.17.0.5:22) to root@172.17.0.3(172.17.0.3:22).. Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts. Warning: Permanently added '172.17.0.3' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:43 2017 - [debug] ok. Sat Nov 4 05:30:43 2017 - [debug] Connecting via SSH from root@172.17.0.5(172.17.0.5:22) to root@172.17.0.4(172.17.0.4:22).. Warning: Permanently added '172.17.0.4' (ECDSA) to the list of known hosts. Sat Nov 4 05:30:44 2017 - [debug] ok. Sat Nov 4 05:30:44 2017 - [info] All SSH connection tests passed successfully.
各个节点状态都是可以的。
-
检查整个复制环境状况
root@mha-manager:~# masterha_check_repl --conf=/etc/masterha/app1.cnf Sat Nov 4 05:46:50 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Sat Nov 4 05:46:50 2017 - [info] Reading application default configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:46:50 2017 - [info] Reading server configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:46:50 2017 - [info] MHA::MasterMonitor version 0.56. Sat Nov 4 05:46:50 2017 - [info] Dead Servers: Sat Nov 4 05:46:50 2017 - [info] Alive Servers: Sat Nov 4 05:46:50 2017 - [info] 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:46:50 2017 - [info] 172.17.0.4(172.17.0.4:3306) Sat Nov 4 05:46:50 2017 - [info] 172.17.0.5(172.17.0.5:3306) Sat Nov 4 05:46:50 2017 - [info] Alive Slaves: Sat Nov 4 05:46:50 2017 - [info] 172.17.0.4(172.17.0.4:3306) Version=5.7.18 (oldest major version between slaves) log-bin:disabled Sat Nov 4 05:46:50 2017 - [info] GTID ON Sat Nov 4 05:46:50 2017 - [info] Replicating from 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:46:50 2017 - [info] Primary candidate for the new Master (candidate_master is set) Sat Nov 4 05:46:50 2017 - [info] 172.17.0.5(172.17.0.5:3306) Version=5.7.18 (oldest major version between slaves) log-bin:disabled Sat Nov 4 05:46:50 2017 - [info] GTID ON Sat Nov 4 05:46:50 2017 - [info] Replicating from 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:46:50 2017 - [info] Current Alive Master: 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:46:50 2017 - [info] Checking slave configurations.. Sat Nov 4 05:46:50 2017 - [info] read_only=1 is not set on slave 172.17.0.4(172.17.0.4:3306). Sat Nov 4 05:46:50 2017 - [warning] relay_log_purge=0 is not set on slave 172.17.0.4(172.17.0.4:3306). Sat Nov 4 05:46:50 2017 - [warning] log-bin is not set on slave 172.17.0.4(172.17.0.4:3306). This host can not be a master. Sat Nov 4 05:46:50 2017 - [info] read_only=1 is not set on slave 172.17.0.5(172.17.0.5:3306). Sat Nov 4 05:46:50 2017 - [warning] relay_log_purge=0 is not set on slave 172.17.0.5(172.17.0.5:3306). Sat Nov 4 05:46:50 2017 - [warning] log-bin is not set on slave 172.17.0.5(172.17.0.5:3306). This host can not be a master. Sat Nov 4 05:46:50 2017 - [info] Checking replication filtering settings.. Sat Nov 4 05:46:50 2017 - [info] binlog_do_db= , binlog_ignore_db= Sat Nov 4 05:46:50 2017 - [info] Replication filtering check ok. Sat Nov 4 05:46:50 2017 - [error][/usr/local/share/perl/5.18.2/MHA/MasterMonitor.pm, ln341] None of slaves can be master. Check failover configuration file or log-bin settings in my.cnf Sat Nov 4 05:46:50 2017 - [error][/usr/local/share/perl/5.18.2/MHA/MasterMonitor.pm, ln401] Error happend on checking configurations. at /usr/local/bin/masterha_check_repl line 48. Sat Nov 4 05:46:50 2017 - [error][/usr/local/share/perl/5.18.2/MHA/MasterMonitor.pm, ln500] Error happened on monitoring servers. Sat Nov 4 05:46:50 2017 - [info] Got exit code 1 (Not master dead). MySQL Replication Health is NOT OK!
出现一条报错信息:
None of slaves can be master. Check failover configuration file or log-bin settings in my.cnf
前面说了,MHA 至少需要三台机器,一台当作 master,两台当作 slave,其中一台 slave 必须做 master 备份,这个地方的报错意思是没有 slave 能够变成 master,我们需要对 my.cnf 做适当修改。
另外,需要将 MySQL 的自动清理中继日志,即relay_log_purge=0
,因为 MHA 依赖中继日志来提升 slave 为 master ,需要 MHA 来进行管理。作为热备的 slave 机器的my.cnf
最终配置如下:root@mha_slave01:/# cat /etc/mysql/my.cnf [mysqld] user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp server-id = 3 log-bin = master-bin log-bin-index = master-bin.index relay_log_purge = 0 relay-log-index = slave-relay-bin.index relay-log = slave-relay-bin gtid-mode = ON log-slave-updates enforce-gtid-consistency
重新检查整个复制环境状况:
root@mha-manager:~# masterha_check_repl --conf=/etc/masterha/app1.cnf Sat Nov 4 05:57:14 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Sat Nov 4 05:57:14 2017 - [info] Reading application default configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:57:14 2017 - [info] Reading server configurations from /etc/masterha/app1.cnf.. Sat Nov 4 05:57:14 2017 - [info] MHA::MasterMonitor version 0.56. Sat Nov 4 05:57:14 2017 - [info] Dead Servers: Sat Nov 4 05:57:14 2017 - [info] Alive Servers: Sat Nov 4 05:57:14 2017 - [info] 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:57:14 2017 - [info] 172.17.0.4(172.17.0.4:3306) Sat Nov 4 05:57:14 2017 - [info] 172.17.0.5(172.17.0.5:3306) Sat Nov 4 05:57:14 2017 - [info] Alive Slaves: Sat Nov 4 05:57:14 2017 - [info] 172.17.0.4(172.17.0.4:3306) Version=5.7.18-log (oldest major version between slaves) log-bin:enabled Sat Nov 4 05:57:14 2017 - [info] GTID ON Sat Nov 4 05:57:14 2017 - [info] Replicating from 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:57:14 2017 - [info] Primary candidate for the new Master (candidate_master is set) Sat Nov 4 05:57:14 2017 - [info] 172.17.0.5(172.17.0.5:3306) Version=5.7.18 (oldest major version between slaves) log-bin:disabled Sat Nov 4 05:57:14 2017 - [info] GTID ON Sat Nov 4 05:57:14 2017 - [info] Replicating from 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:57:14 2017 - [info] Current Alive Master: 172.17.0.3(172.17.0.3:3306) Sat Nov 4 05:57:14 2017 - [info] Checking slave configurations.. Sat Nov 4 05:57:14 2017 - [info] read_only=1 is not set on slave 172.17.0.4(172.17.0.4:3306). Sat Nov 4 05:57:14 2017 - [info] read_only=1 is not set on slave 172.17.0.5(172.17.0.5:3306). Sat Nov 4 05:57:14 2017 - [warning] relay_log_purge=0 is not set on slave 172.17.0.5(172.17.0.5:3306). Sat Nov 4 05:57:14 2017 - [warning] log-bin is not set on slave 172.17.0.5(172.17.0.5:3306). This host can not be a master. Sat Nov 4 05:57:14 2017 - [info] Checking replication filtering settings.. Sat Nov 4 05:57:14 2017 - [info] binlog_do_db= , binlog_ignore_db= Sat Nov 4 05:57:14 2017 - [info] Replication filtering check ok. Sat Nov 4 05:57:14 2017 - [info] GTID is supported. Skipping all SSH and Node package checking. Sat Nov 4 05:57:14 2017 - [info] Checking SSH publickey authentication settings on the current master.. Sat Nov 4 05:57:14 2017 - [info] HealthCheck: SSH to 172.17.0.3 is reachable. Sat Nov 4 05:57:14 2017 - [info] 172.17.0.3 (current master) +--172.17.0.4 +--172.17.0.5 Sat Nov 4 05:57:14 2017 - [info] Checking replication health on 172.17.0.4.. Sat Nov 4 05:57:14 2017 - [info] ok. Sat Nov 4 05:57:14 2017 - [info] Checking replication health on 172.17.0.5.. Sat Nov 4 05:57:14 2017 - [info] ok. Sat Nov 4 05:57:14 2017 - [warning] master_ip_failover_script is not defined. Sat Nov 4 05:57:14 2017 - [warning] shutdown_script is not defined. Sat Nov 4 05:57:14 2017 - [info] Got exit code 0 (Not master dead). MySQL Replication Health is OK.
环境测试完毕。
-
-
-
启动 MHA Manager
root@mha-manager:~# nohup masterha_manager --conf=/etc/masterha/app1.cnf > /var/log/masterha/app1/manager.log 2>&1 &
启动参数介绍:
--remove_dead_master_conf 该参数代表当发生主从切换后,老的主库的ip将会从配置文件中移除。 --manger_log 日志存放位置 --ignore_last_failover 在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件,默认情况下,MHA发生切换后会在日志目录,也就是上面我设置的/data产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。
查看 MHA Manager 监控是否正常:
root@mha-manager:~# masterha_check_status --conf=/etc/masterha/app1.cnf app1 (pid:4649) is running(0:PING_OK), master:172.17.0.3
可以看到 MHA Manager 已经跑起来了。
-
验证
-
测试master(201)宕机后,是否会自动切换?
停掉 mha_master
➜ ~ docker stop mha_master mha_master
会有如下输出:
----- Failover Report ----- app1: MySQL Master failover 172.17.0.3 to 172.17.0.4 succeeded Master 172.17.0.3 is down! Check MHA Manager logs at mha-manager:/var/log/masterha/app1/manager.log for details. Started automated(non-interactive) failover. Selected 172.17.0.4 as a new master. 172.17.0.4: OK: Applying all logs succeeded. 172.17.0.5: OK: Slave started, replicating from 172.17.0.4. 172.17.0.4: Resetting slave info succeeded. Master failover to 172.17.0.4(172.17.0.4:3306) completed successfully.
说明切换成功。切换后 MHA Manager 会退出。
这里需要注意:
一旦发生切换管理进程(Manager)将会退出,无法进行再次测试,需将故障数据库解决掉之后,重新change加入到MHA环境中来,并且要保证app1.failover.complete不存在或则加上--ignore_last_failover参数忽略,才能再次开启管理进程。
-