高可用和负载均衡

负载均衡

负责均衡服务器根据负载均衡算法(轮询,随机,哈希,权重等)来分发请求到不同的主服务器。

每个主服务器都是等价的,都可以完成相同的功能

容错是负载均衡服务器里面的一个概念。是指当一台主服务器宕机后,集群能够继续提供服务的策略。比如说当主服务器A宕机后,负载均衡服务器要能发现主服务器A不能继续提供服务了,以前分发到主服务器A的请求要分发到其它主服务器。这种处理就是容错处理。

高可用

高可用的含义就是当一台服务器宕机后,服务可以继续使用以及数据不会丢失。

如果是负载均衡集群,当负载均衡服务器宕机后,整个服务就不可以使用了。
如果是主服务器A宕机后,即使原本分发到主服务器A的请求可以重新分发到主服务器B,主服务器A上的缓存数据也会丢失,所以说只用负载均衡集群无法提供高可用。

实现高可用的思想很简单,就是采用主从(master->slave)备份。从服务器为主服务器的备份,当主服务器宕机后,根据一定算法从所有从服务器中再挑选出一台服务器来作为主服务器继续提供服务。

高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。

假设系统一直能够提供服务,我们说系统的可用性是100%。

如果系统每运行100个时间单位,会有1个时间单位无法提供服务,我们说系统的可用性是99%。

很多公司的高可用目标是4个9,也就是99.99%,这就意味着,系统的年停机时间为8.76个小时。

百度的搜索首页,是业内公认高可用保障非常出色的系统,甚至人们会通过www.baidu.com 能不能访问来判断“网络的连通性”,百度高可用的服务让人留下啦“网络通畅,百度就能访问”,“百度打不开,应该是网络连不上”的印象,这其实是对百度HA最高的褒奖。

单点是系统高可用的大敌,单点往往是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。方法论上,高可用保证的原则是“集群化”,或者叫“冗余”:只有一个单点,挂了服务会受影响;如果有冗余备份,挂了还有其他backup能够顶上。

保证系统高可用,架构设计的核心准则是:冗余。

有了冗余之后,还不够,每次出现故障需要人工介入恢复势必会增加系统的不可服务实践。所以,又往往是通过“自动故障转移”来实现系统的高可用。

什么是mysql 的主从复制

一台服务器充当主服务器,另一台或者多台充当从数据库服务器,主服务器中的数据自动复制到从服务器中。

对于多级复制,主从关系可以呼唤。复制的基础是主服务器对数据库修改记录的二进制文件bin log,从服务器通过主服务器的二进制日志自动执行更新。

复制的类型

  1. 基于语句复制: 主库把sql语句写入到bin log 中,完成复制
  2. 基于行数据的复制: 主库把每一行数据变化的信息作为事件,写入到bin log,完成复制
  3. 混合复制:上面两个结合体,默认用语句复制,出问题时候自动切换成行数据复制

tip:和上面相对应的日志格式也有三种:STATEMENT,ROW,MIXED。

日志格式

  1. STATEMENT模式(SBR)
    每一条会修改数据的sql语句会记录到binlog中。优点是并不需要记录每一条sql语句和每一行的数据变化,减少了binlog日志量,节约IO,提高性能。缺点是在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)

  2. ROW模式(RBR)
    不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。而且不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。缺点是会产生大量的日志,尤其是alter table的时候会让日志暴涨。

  3. MIXED模式(MBR)
    以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

主从复制原理

  1. Master 数据库只要发生变化,立马记录到Binary log 日志文件中
  2. Slave数据库启动一个I/O thread连接Master数据库,请求Master变化的二进制日志
  3. Slave I/O获取到的二进制日志,保存到自己的Relay log 日志文件中。
  4. Slave 有一个 SQL thread定时检查Realy log是否变化,变化那么就更新数据

主从复制过程

在master机器上的操作

当master上的数据发生改变的时候,该事件(insert、update、delete)变化会按照顺序写入到binlog中。

当slave连接到master的时候,master机器会为slave开启binlog dump线程。如果读取的进度已经跟上了master,就进入睡眠状态并等待master产生新的事件。

当master 的 binlog发生变化的时候,binlog dump线程会通知slave,并将相应的binlog内容发送给slave。

在slave机器上的操作

当主从同步开启的时候,slave上会创建2个线程。

I/O线程。该线程连接到master机器,master机器上的binlog dump线程会将binlog的内容发送给该I/O线程。

该I/O线程接收到binlog内容后,再将内容写入到本地的relay log。

SQL线程。该线程读取I/O线程写入的relay log。并且根据relay log的内容对slave数据库做相应的操作。

为什么要用mysql 的主从

  1. 实现服务器负载均衡
    即可以通过在主服务器和从服务器之间切分处理客户查询的负荷,从而得到更好的客户相应时间。通常情况下,数据库管理员会有两种思路。

    一是在主服务器上只实现数据的更新操作。包括数据记录的更新、删除、新建等等作业。而不关心数据的查询作业。数据库管理员将数据的查询请求全部 转发到从服务器中。这在某些应用中会比较有用。如某些应用,像基金净值预测的网站。其数据的更新都是有管理员更新的,即更新的用户比较少。而查询的用户数 量会非常的多。此时就可以设置一台主服务器,专门用来数据的更新。同时设置多台从服务器,用来负责用户信息的查询

    二是在主服务器上与从服务器切分查询的作业。在这种思路下,主服务器不单单要完成数据的更新、删除、插入等作业,同时也需要负担一部分查询作业。而从服务器的话,只负责数据的查询。当主服务器比较忙时,部分查询请求会自动发送到从服务器重,以降低主服务器的工作负荷。

  2. 通过复制实现数据的异地备份
    可以定期的将数据从主服务器上复制到从服务器上,这无疑是先了数据的异地备份。在传统的备份体制下,是将数据备份在本地。此时备份 作业与数据库服务器运行在同一台设备上,当备份作业运行时就会影响到服务器的正常运行。有时候会明显的降低服务器的性能。同时,将备份数据存放在本地,也 不是很安全。如硬盘因为电压等原因被损坏或者服务器被失窃,此时由于备份文件仍然存放在硬盘上,数据库管理员无法使用备份文件来恢复数据。这显然会给企业 带来比较大的损失。

  1. 提高数据库系统的可用性
    数据库复制功能实现了主服务器与从服务器之间数据的同步,增加了数据库系统的可用性。当主服务器出现问题时,数据库管理员可以马上让从服务器作为主服务器,用来数据的更新与查询服务。然后回过头来再仔细的检查主服务器的问题。此时一般数据库管理员也会采用两种手段。

    一是主服务器故障之后,虽然从服务器取代了主服务器的位置,但是对于主服务器可以采取的操作仍然做了一些限制。如仍然只能够进行数据的查询,而 不能够进行数据的更新、删除等操作。这主要是从数据的安全性考虑。如现在一些银行系统的升级,在升级的过程中,只能够查询余额而不能够取钱。这是同样的道 理。

    二是从服务器真正变成了主服务器。当从服务器切换为主服务器之后,其地位完全与原先的主服务器相同。此时可以实现对数据的查询、更新、删除等操 作。为此就需要做好数据的安全性工作。即数据的安全策略,要与原先的主服务器完全相同。否则的话,就可能会留下一定的安全隐患

怎么配置主从

mysql 配置文件配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#mysql master1 config 
[mysqld]
server-id = 1 # 节点ID,确保唯一

# log config
log-bin = mysql-bin #开启mysql的binlog日志功能
sync_binlog = 1 #控制数据库的binlog刷到磁盘上去 , 0 不控制,性能最好,1每次事物提交都会刷到日志文件中,性能最差,最安全
binlog_format = mixed #binlog日志格式,mysql默认采用statement,建议使用mixed
expire_logs_days = 7 #binlog过期清理时间
max_binlog_size = 100m #binlog每个日志文件大小
binlog_cache_size = 4m #binlog缓存大小
max_binlog_cache_size= 512m #最大binlog缓存大
binlog-ignore-db=mysql #不生成日志文件的数据库,多个忽略数据库可以用逗号拼接,或者 复制这句话,写多行

auto-increment-offset = 1 # 自增值的偏移量
auto-increment-increment = 1 # 自增值的自增量
slave-skip-errors = all #跳过从库错误
1
2
3
4
5
6
7
[mysqld]
server-id = 2
log-bin=mysql-bin
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%

重启两个mysql,让配置生效

master数据库,创建复制用户并授权
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
CREATE USER repl_user IDENTIFIED BY 'repl_passwd';

grant replication slave on *.* to 'repl_user'@'172.17.0.2' identified by 'repl_passwd';

FLUSH PRIVILEGES;

# 查看状态
show master status;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 120| | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

# 配置从库

mysql> CHANGE MASTER TO
MASTER_HOST = '172.17.0.3',
MASTER_USER = 'repl_user',
MASTER_PASSWORD = 'repl_passwd',
MASTER_PORT = 3307,
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=120,
MASTER_RETRY_COUNT = 60,
MASTER_HEARTBEAT_PERIOD = 10000;

# MASTER_LOG_FILE='mysql-bin.000005',#与主库File 保持一致
# MASTER_LOG_POS=120 , #与主库Position 保持一致
# 启动slave 进程
mysql> slave start;
Query OK, 0 rows affected (0.04 sec)