1,为什么需要mysql复制技术,有什么用?
单台数据库服务器的能力总是有限的。根据专业人士的经验,一台8核心32G配置的服务器,承受50~200的并发连接请求,算是很好了。mysql复制是提升数据存储层面能力的一种方式。
 

2,怎么提升数据库性能?

那么提升数据库性能有两个途径:1,提升硬件配置。2,增加服务器数量。 
对于1,性价比很低。这个属于垂直扩展,专业名字叫scale up
对于2,就是集群技术,属于水平扩展,也叫scale out
 

集群技术是一种把多台服务器当做一台来使用的技术。应用层面与存储层分离,不需要考虑存储层的变化对应用层的影响。那数据库可以做集群吗?
 
 

3,数据存储层面的怎么扩展?

其实我们公司目前的设计,是在应用层把不同的用户的访问请求定位到不同的数据库服务器。应用层面直接去找用户对应的数据库服务器ip,建立连接进行访问。一般来说,单个用户有一定数量的终端设备。每个设备与通信服务器建立连接(通信服务器这里可做集群扩展),通信服务器与数据存储层交互。
 
我们给每一个用户建立一个数据库,在这个数据库下面给用户拥有的每一个终端设备,建立一张表。在数据库的层面分流负载。
 
这个设计的问题:
我们的设计中,通信服务器与数据库服务器之间需要预先建立一定数量的连接(或者改为动态?)。
1,比如有一台通信服务器,一台mysql服务器。通信服务器与数据库预服务器先建立30个连接。这是OK的。随着访问请求的增长,一般数据库的承受能力先到上限,考虑增加数据库的数量,分流负载。

2,一台通信服务器,多台mysql服务器。通信服务器与每一个数据库服务器都建立30个连接。(通信服务器承受能力>数据库的承受能力)。访问请求继续增长,通信服务器的承受能力也到了上限,考虑增加通信服务器数量。

3,多台通信服务器,多台mysql服务器。每一个通信服务器与每一个数据库服务器建立30个连接。
这里就要考虑mysql最多可以有多少个并发连接,性能会不会下降,下降多少?这里可能是一个限制条件。比如3台通信服务器,每个数据库就有3*30=90个连接。这个会不会有问题。


负载测试:

 1,逻辑上,一台通信服务器,一台mysql服务器。物理上,可以在一台机器上,也可以在两台机器上。分两种情况测试。观察网络负载,cpu,内存,磁盘I/O的使用情况。得出这个架构可以承受的最大终端数。
 2,同上

 3,同上
 

这是题外话,先继续吧。。。
 

4. mysql的复制技术
 

4.1 mysql复制的结构

其实通过mysql复制,只可以提升数据存储层对于读请求的响应能力,无法提升对于写请求的响应能力。

结构:
 1,一主一从

    主----->从

 

2,一主多从
    主----->从
           |-->从
           |-->从
  主节点网络IO,磁盘IO的压力看起来比较大
  
 3,层级结构
      主----->从----->从
             |-->从     |-->从  
 主节点的复制工作量相对一主多从,要轻一些
 
 
主节点可读可写,从节点只能读。
 
4.2 从节点多了产生的问题

从节点多了之后,应用程序对从节点的读操作,也需要做负载均衡啊。
对于mysql这种有缓存的应用,做负载均衡会又面临一个缓存命中的问题。
 
4.2.1 负载均衡与缓冲命中

mysql缓存,是用来提高响应速度。因为内存的访问速度远远大过磁盘。把一部分经常用到
的数据预先放入内存里面,大部分的查询只要在内存里面读取数据,那就不用每一次查询都去读磁盘的文件,那太耗费时间了。比如100次的查询操作,有90次在内存里面读数据,10次去磁盘读数据,那缓存命中率就是90%了。
 
毕竟内存的大小,相对于磁盘的大小还是比较小的,数据量一直也在增长。不可能说把磁盘里的数据全部都缓存到内存中,那样命中率就100%了。内存空间毕竟有限,只能缓存一定量的数据。如果这一定量的数据比较稳定,变动不是很大,那样命中率就能高一点。所以多个从节点,各自有一些分工的话,各自应对某一类的查询,就可以提高这个命中率。
出于这个考虑,根据sql语句进行分类,分配到各个从节点。


4.2.1.1 提高缓存命中的方式:

分类有几种方式:
 1,取模
对sql语句做散列运算得出特征值,用这个值对节点数取模,比如有三个节点,取模可能得到0,1,2。0,1,2分别对应着一个节点。这个sql查询就被分配到这个取模结果对应的节点了。


计算式:sql语句特征值/节点数 =0~2 ------> 0节点
                                    |---> 1节点
                                    |---> 2节点
缺点:

节点数一旦变化,如新加一个节点,或因为节点失效删除一个节点,计算式“sql语句的特征值/节点数” 所得到的结果都可能产生变化,sql的分配大范围变化,所有节点上原来已经比较稳定的缓存,需要一定时间才能重新稳定下来。这期间的整体响应性能就不太稳定了。
  
 2,一致性hash
  对于节点增删引起的缓存抖动,一致性hash可以把这个抖动限制在一个较小的范围。
  
  计算式:sql语句特征值/(2^32)= 0 ~ 2^32-1
                节点特征值/(2^32)= 0 ~ 2^32-1
  
  节点和sql语句都落在一个0 ~ 2^32-1的环上。
  一个节点失效的话,影响范围缩小到这个节点和逆时针方向上一个节点之间的sql语句。
  
缺点:节点分布不均,导致节点的承受的负载不均。
  
 3,虚拟节点
真实节点虚拟成多个虚拟节点,均匀分布在0 ~ 2^32-1的环上。节点的负载更均匀。
ps: 数学是短板啊,死脑细胞。
  
公共缓存memcached: 

以上是在程序层面考虑,提高缓存命中的方法。
另外有一种公共缓存的方式:memcached, 具体不清楚,先知道有这样一种方法吧。。

应用层面跟数据存储层面,耦合度最好小一点,应用层就不需要太关心数据存储层的变化,不受太多影响,这里引出下面一个话题:mysql读写分离工具。
 


4.3 mysql读写分离工具(有哪些?):
其实就是在应用层和数据存储层之间增加一个中间层,它可以理解sql语句是读还是写,    然后把写的操作分配到主节点,把读的操作分配到从节点。就像一个sql语句的路由器。
 
 
4.4 那mysql复制可以解决一些什么问题?
  扩展和负载均衡
  高可用
  数据分布
  数据备份
  mysql升级测试,不可能在主节点去做测试吧。。
  
 先知道有这样一些概念,具体还讲不太清楚。
 
4.5 mysql复制架构有什么缺陷?
前面也提到过,从节点只能读,不能写,所以这个架构对于写入的能力没有提升的效果。
而且,主节点是单节点,如果主节点挂了,怎么恢复?从节点倒没什么,挂了只是会影响访问速度。
  

解决方案:
   1,表分散到不同的节点(垂直分割)
   2,当一个表的访问量很大的时候,对表做分片(水平分割)

怎么分呢,是根据一个字段来分,比如1~10000分到节点1,10001~20000分到节点2 
自然也需要有一个全局管理者,知道哪些范围的数据在哪个节点。
    
写入操作涉及的节点越多,写入速度会越快,因为写入负载被分散
查询操作涉及的节点越多,查询就越慢,因为要把各个分散的数据集中读取到内存,再
排序,返回结果,比较的麻烦。
    
这里也不应该忘记sql语句的设计,不要太糟糕。。
    
简单来说,mysql复制可以提供读的扩展,而写的扩展,需要分表,或分片。
 

最后,来说说mysql复制的工作原理吧。
 
4.6 mysql复制是怎么实现的?
mysql复制需要主节点打开二进制日志。
  
二进制日志(记录所有写入,更新,删除等引起数据发生变动的操作):
记录方式:
    1,statment语句记录
     记录sql语句,问题:now()函数等
    2,raw行记录
     问题:导致记录量增加
     比如某一个更新操作涉及1000行数据,一个sql语句可以表达出来
     但记录行的话,就要增加1000条记录。
    3,mix混合方式记录
     综合前两种方式,尽量避免各自的问题。由mysql来判断什么时候
     使用语句记录,什么时候使用行记录。
  

复制是如何进行的:
  从节点的IO线程会去主节点的3306端口,请求读取二进制日志事件对应的数据。
  主节点这时启动dump线程,从二进制日志中读取数据,读取一条,发一条,发给
  从节点的IO线程。
  从节点收到数据后,写入本地的中继日志。从节点的sql线程,从中继日志中读取数据,
  读取一条,在本地执行一次。从节点一般关闭二进制日志,避免额外的开销。
  
  二进制日志中,会记录产生这个事件的服务器的id号。
  复制架构里面,每个节点有各自不同的id号。
  
  要知道复制是异步的,因为主节点的数据写入,如果要等待从节点复制完成,再返回,
  那响应速度恐怕不太好。
  
  问题:从节点的数据可能落后与主节点的数据。
  
从节点可以多个主节点吗?
不行,只能有一个。

(MariaDB支持多主复制,但不是复制同一个数据库,从不同主节点复制不同的数据库)

  
双主复制模型:

两个节点,又是主节点,又是从节点。
问题:

1,自增长id,一个id为奇数,一个为偶数,id增长步进为2,可避免id冲突。
2,数据不同步,同一时间,同一条记录被修改
     年龄 工资
     A 40, +1000
     B <3000, -2
     
     41岁,工资2800
     A 41,3800
     B 39,2800
 
    造成数据不同步


双主模型的作用:
    高可用
    读操作负载均衡
    写操作则没有起到均衡效果(因为每一个写操作在两边都会发生,区别在于直接写
    还是通过复制写)

双主复制适用于什么场景

一般来说,MySQL主主复制一般是为了保证主备数据一致。

应用访问MySQL,如果只有一台MySQL,MySQL挂了,数据库就不能提供服务。但是如果有两台MySQL,并且搭建了主主复制,那么其中的一台挂掉以后,另外一台可以立刻提供服务。并且原MySQL启动以后,复制赶上以后就可以提供服务。DBA维护工作量比较少。如果是主从复制,主机挂了,备机顶替上来。主机需要搭建从备机来的复制,那么就需要找位置,change master等。

另外,主主复制还有一种用法,在业务压力比较大的时候,按照应用垂直拆分,分布到两个MySQL上,共同承担压力。(此节回答来自AskHelloDBA