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
造成数据不同步
双主模型的作用:
高可用
读操作负载均衡
写操作则没有起到均衡效果(因为每一个写操作在两边都会发生,区别在于直接写
还是通过复制写)