MySQL Replication
系统扩展的方式:
scale up:向上扩展,垂直扩展 使用更高性能的硬件来扩展
scale out:向外扩展,水平扩展 提供更多的节点来提供更多的访问需求
复制:水平扩展的一种方案
如果构建一个httpd负载均衡集群会面临的问题:
当用户请求到达时,负载均衡器给调度到后端的各realserver上,如果web服务器允许用户上传数据,用户上传数据到第一个节点上,而后他又访问被调度到第三个节点上来,则数据就访问不到,如果要解决此问题,需要如何操作?使用共享存储,使用共享存储是块级别的共享存储还是文件级别的共享存储?文件级的为nas 块级别的为san ?
文件级别在系统调用接口上通常性能比块级别低,如果是块级别前端多个节点如果同时读写同一个文件,那怎么办?会出现资源争用 出现资源争用,如何解决此问题?把集群节点都做成高可用集群,做分布式文件锁,做成集群文件系统,而做集群文件系统,多个节点同时访问同一个文件时,节点数是很有限的,集群文件系统支持到16个节点基本上是上限了。
nas 文件级别性能很差,尤其是当节点大于4时。
这些节点都是共享存储,最理想的方式就是在本地存储,本地存储无法共享?有两三个节点时rsync是一种解决方案,大了性能就很低了
容量和访问量都很大时,需要使用分布式文件系统,前端有一个主控节点【集中式控制节点】,后端是大量节点
也有的是无主控节点,使用比较麻烦
分布式文件系统主要用来存储非结构化数据的,那结构化数据呢?如论坛一个帖子,需要存储在数据库服务器上,通常为MySQL服务器,也即在后端需要MySQL服务器,结构化数据需要放在数据库服务器上,MySQL也面临多个节点同时访问的问题,这里是不会出现资源争用问题的,因为MySQL自身会添加锁,其智能性都在MySQL上,如果是少量节点对MySQL读写是不会产生问题的,如果很多节点时,MySQL则应付不了那么多节点的请求,
开始时,解决方案就是向上进行扩展,由于向上扩展很容易达到极限
因此需要进行水平扩展,多台MySQL服务器,数据如何存放?MySQL服务器后台用共享存储?在什么级别共享? nas san?如果使用nas时,会出现资源争用,是解决不了此种情况的,此时就需要使用到MySQL复制功能(主从复制),所有前端节点的更新请求在主节点山,从节点在主节点上把数据复制一份,放在当前节点上,因此从节点和主节点都有一模一样的数据,前端读请求在从服务器上,主节点可读可写,从节点只能读,复制是单方向的,从主到从节点,
可以有多个读节点,在多个读节点上,则需要实现负载均衡,读请求实现负载均衡存在缺陷,MySQL本地有查询缓存,同一条语句发起的请求会负载在另外一个位置上,因此缓存就不能命中了,如果说后端有多个具有缓存能力的节点,这些节点缓存数据不一定相同,则需要提供解决方案来解决缓存命中率,有两种解决方案:
1.1在前端自己做负载均衡,也即在程序中如果请求语句是同一个服务器,则其将重复发到同一个节点上,根据语句做均衡,如何操作? 做取余法,每一个语句在向后端发起查询请求时,如何挑选?在应用程序中对查询语句做hash计算,取得其校验码,取得校验码后对服务器个数做取模计算,同一个数据的特征码是一样的,特征码一样取模结果就一定相同,此时,同一条语句会始终发送到同一个服务器。但是此种情况会存在一个问题了,当要添加和删除服务器时会导致所有缓存都命中不到了。
1.2解决上面方案的方法,使用一致性hash算法,把每一个节点的服务器都计算其hash码,对2^23取模,把0-2^32的数字均匀的分布到一个环上,把服务器分散到环上,每一个查询语句用hash计算后对2^32取模,取模后一定会落到环上,查询就是落到节点按顺时针到离他最近的节点,如果某节点坏了,则只影响部分缓存,
存在的问题:一致性hash有可能是偏斜的,也即各节点分布不均衡,导致压力不同
节点所在位置的hash所落在位置,此改进需要设置虚拟节点算法,把每一个节点通过用算法计算多次,也即一个节点可以在环上落n次,每一个节点都做单独计算
此时缓存命中就得到大的提升
缓存命中:
应用程序:(两种方法)
除模
一致性哈希
此时,缓存对程序的依赖还是很大的,如何减少耦合性,减少依赖,添加中间层,中间层可以理解MySQL语句,MySQL的反向代理,无论谁发来请求时,此节点知道到对应的位置做查询操作,知道操作是读还是写,能实现智能的将写请求发给主节点,读请求负载均衡到多个从节点,此节点叫MySQL代理(读写分离器)
读写分离器:
语句路由 核心功能MySQL的语句路由
制的功用:
负载均衡 将读写分开,读到多个节点
数据分布 数据分开到多个节点,避免带宽压力过大
备份 每一个节点数据是一样的
高可用性 从服务器可以出现宕机
MySQL升级测试
复制架构的问题:
1、主节点是单点故障所在
2、写操作无法有效均衡 写操作过多时,无法均衡
对写操作做负载均衡,此时数据必须切开,将关联性不是很大的表分开存储,切开后每一个服务器都要各自复制,垂直切分 切割后存在的问题,数据有热点 有些热点集中在一个表上 再横向切割,按id进行切割 1-10W 10W-30W 。。。在不同的节点上,那切割后如何进行查询呢?读请求出现压力过大了,把数据库服务器节点找一个路由器实现统一路由,数据库如何进行切片?前端找一个节点,切的时候根据某个字段来切,
切割时把握的两个原则,读尽可能集中在有限节点或几个节点上,读节点越少越好,写节点越多越好,分担写
数据库扩展的思路两个:
复制、切片
MySQL复制的工作原理:
以两个节点为例:
MySQL日志类型:查询日志、慢查询日志、错误日志、二进制日志、事务日志、中继日志等
二进制日志的格式:记录的是能够引起数据库中的数据发生改变或者潜在影响其改变的那些语句 格式有三种:
语句: statement 基于语句来记录,能记录的数据量很小,存在的问题,如:记录使用某个函数生成的时间,在另外一个服务器上执行以后时间一定是不同的
行: row 能够提供精确数据,存在的问题如:发工资,每个人月薪加3000,基于语句时,一条update语句即可,基于行时,有很多人就要记录很多人的数据
混合:mixed 由MySQL自行智能决定
复制就是在从服务器上把主服务器上的二进制日志复制到本地重新走一遍,如何走?从服务器把自身认为是MySQL的客户端去连接主服务器,连到主服务器后不是做任何的查询操作,而是请求MySQL进程读其二进制日志,主服务器会启动一个dump线程,dump线程会从文件读取一个事件发送一个事件,从服务器接收到事件后,先把数据存下来,存取下来的文件叫中继日志,存下来以后,MySQL会启动一个线程sql ,此线程会从文件中读取语句并执行,
主服务器上启用二进制日志,启动的线程是dump线程,而在从服务器上有两个线程,
io线程和sql线程。io线程负责请求MySQL服务器,MySQL服务器会在必要时,有事件产生,会启动dump线程,在里面读取数据后,发送给从服务器,从服务器发给io线程,io线程读取后,保存在本地的中继日志中,sql线程从中继日志中读语句执行。从服务器读取后是否会产生二进制日志?从服务器上也会产生二进制日志(一般从服务器会关闭二进制日志功能),
复制有三个步骤:
1、在主库上启用二进制日志;
2、备库从主库复制二进制日志,并保存至本地的中继日志中;
3、备库从中继日志中读取事件并于本地执行一次;
在二进制日志中每一个日志事件会保存生成这个二进制日志的服务器的id号,在复制中,每一个服务器都有其唯一的一个id号。其id号有什么作用呢?避免造成环形复制。
MySQL复制支持双主模型:
master/master 都能写都能读
每一次本地请求都会记录到二进制日志中,而每一个节点同时作为对方的从节点,此时存在问题,会出现无限循环,如何解决此问题?给每一个服务器都记录好server-id,在哪个服务器上产生的,真正应用时,只应用id号为非本机日志事件,所以每一个服务器必须有存在一个唯一的id号
主主复制时,负载均衡就不存在了,因为本地不写也要从对方复制过来进行写操作,只起到高可用的作用。
主主复制问题:
1、自动增长的ID字段:解决:一端是偶数 一端是奇数
各自使用不同的数值:偶数或奇数
2、一张表中有:
年龄 工资 两个字段,在第一个主节点上,执行了根据年龄修改工资,在第二个节点上执行了根据工资修改年龄
大于40岁,工资+1000
所有工资为3000以下的,-2 年龄减2
加入用户年龄41岁,工资2800 则结果为什么?
41,3800 左节点
39,2800 右节点
此时就会对结果产生影响了
第三方项目:mmm: multi master mysql 多主MySQL,大量perl脚本
mha: mysql ha
MySQL复制:是异步进行 不建议使用双主模型
复制总结:
master:启用二进制日志,有惟一的server-id
binlogdump: 将从服务的io thread发出读取二进制日志事件的请求对应的数据发送给对方
slave:启用中继日志,并闭二进制日志(建议),有惟一的server-id
IOthread:向master请求二进制日志中的事件
SQLthread:从中继日志中读取事件并在本地执行
复制工作架构:
从服务器:有且只能有一个主服务器,避免从服务器混乱;
MariaDB10:支持多源复制,即支持多个主服务器;
主服务器:可以有多从
可否多级复制? 可以,中间从服务器需要启用二进制日志功能
异步:存在的问题从服务器的数据可能会落后于主服务器
提高缓存命中率的解决思路:
1、在程序中的解决:
取模
一致性哈希
2、使用公共缓存
memcached(引入的问题:一个服务器扛不住,做负载均衡,又存在缓存问题,又要使用到 取模 一致性hash)【只要是缓存服务器都会存在这样的问题】
参考:
http://wdllife.blog.51cto.com/6615958/1627136