1.Scale(扩展):从数据库来看,就是让数据库可以提供更强的服务能力前端 ScaleOut: 是经过增长处理节点的方式来提升总体处理能力mysql ScaleUp: 是经过增长当前处理节点的处理能力来提升总体的处理能力ios 2.事务最小化原则:算法 避免分布式事务的解决方案sql a)进行ScaleOut 设计的时候合理设计切分规则,尽量保证事务所需数据在同一个MySQLServer 上,避免分布式事务。大多数时候也只能兼顾到一些大部分的核心事务,不是一个很完美的解决方案。shell b)大事务切分红多个小事务,数据库保证各个小事务的完整性,应用控制各个小事务之间的总体事务完整性。数据库 c)结合上述两种解决方案,整合各自的优点,避免各自的弊端。核心业务的事务用a)方案保证,其余的用b)保证,要仔细分析,是否须要事务,若是不须要的话,就不要引入事务.后端 3.数据一致性原则.缓存 如何在ScaleOut 的同时又较好的保证数据一致性呢?安全 ==>BASE模型,即:基本可用,柔性状态,基本一致和最终一致。这几个词看着挺复杂挺深奥,其实你们能够简单的理解为非实时的一致性原则。也就是说,应用系统经过相关的技术实现,让整个系统在知足用户使用的基础上,容许数据在必定时间内处于非实时状态,而经过后续技术来保证数据在最终保证处于一致状态。 但也有问题: 第一个问题就是咱们须要让全部数据都是非实时一致吗? ==>若是不是全部的数据都是非实时一致,那咱们又该如何来肯定哪些数据须要实时一致哪些数据又只须要非实时的最终一致呢?其实这基本能够说是一个各模块业务优先级的划分,对于优先级高的天然是规属于保证数据实时一致性的阵营,而优先级略低的应用,则能够考虑划分到容许时间端内不一致而最终一致的阵营。这是一个很是棘手的问题。须要经过很是详细的分析和仔细的评估才能做出决定。由于不是全部数据均可以出如今系统能不时间段内不一致状态,也不是全部数据均可以经过后期处理的使数据最终达到一致的状态,因此之少这两类数据就是须要实时一致的。 如何让系统中的不一致数据达到最终一致? ==>通常来讲,咱们必须将这类数据所设计到的业务模块和须要实时一致数据的业务模块明确的划分开来。而后经过相关的异步机制技术,利用相应的后台进程,经过系统中的数据,日志等信息将当前并不一致的数据进行进一步处理,使最终数据处于彻底一致状态。对于不一样的模块,使用不一样的后台进程,既能够避免数据出现紊乱,也能够并发执行,提升处理效率。 避免实时一致与最终一致两类数据的前台在线交互。 ==>因为两类数据状态的不一致性,极可能会致使两类数据在交互过程当中出现紊乱,应该尽可能让全部非实时一致的数据和实时一致数据在应用程序中获得有效的隔离。甚至在有些特别的场景下,记录在不一样的MySQLServer中来进行物理隔离都是有必要的。 4.高可用以及数据安全原则: 通过ScaleOut设计以后,系统总体可扩展性确实是会获得很大的提升,总体性能天然也很容易获得较大的改善。可是,系统总体的可用性维护方面倒是变得比之前更为困难。由于系统总体架构复杂了,不管是应用程序仍是数据库环境方面都会比原来更为庞大,更为复杂。这样所带来的最直接影响就是维护难度更大,系统监控更难。 ScaleOut 设计过程当中另外一个原则,也就是高可用性的原则。不论如何调整设计系统的架构,系统的总体可用性不能被下降。 数据安全: ==>咱们必须保证在出现软/硬件故障的时候,可以保证咱们的数据不会出现丢失。数据一旦丢失,根本就无可用性可言了。 ==>最好的办法就是经过冗余机制来保证。全部软硬件设备都去除单点隐患,全部数据都存在多份拷贝。能够经过MySQLReplication,MySQLCluster 等技术来实现。 mysqlreplication: 原理: Mysql的Replication是一个异步的复制过程,在Master与Slave之间的实现整个复制过程主要由三个线程来完成,其中两个线程(Sql线程和IO线程)在Slave端,另一个线程(IO线程)在Master端。 要实现MySQL的Replication,首先必须打开Master端的BinaryLog(mysqlbin.xxxxxx)功能,不然没法实现。由于整个复制过程实际上就是Slave从Master端获取该日志而后再在本身身上彻底顺序的执行日志中所记录的各类操做。 复制的过程: 1.Slave 上面的IO线程链接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)以后的日志内容; 2.Master 接收到来自Slave的IO线程的请求后,经过负责复制的IO线程根据请求信息读取指定日志指定位置以后的日志信息,返回给Slave端的IO线程。返回信息中除了日志所包含的信息以外,还包括本次返回的信息在Master端的BinaryLog文件的名称以及在BinaryLog 中的位置; 3.Slave 的IO线程接收到信息后,将接收到的日志内容依次写入到Slave端的RelayLog 文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的binlog的文件名和位置记录到master-info文件中,以便在下一次读取的时候可以清楚的高速Master“我须要从某个bin-log的哪一个位置开始日后的日志内容,请发给我” 4.Slave 的SQL线程检测到RelayLog 中新增长了内容后,会立刻解析该Log文件中的内容成为在Master端真实执行时候的那些可执行的Query语句,并在自身执行这些Query。这样,实际上就是在Master端和Slave端执行了一样的Query,因此两端的数据是彻底同样的。 复制的级别:能够基于语句的/也能够基于一条记录的 记录级别:为每一行都生成sql,信息量大. 语句级别:性能高.可是bug多.尽可能少使用存储过程. 经常使用复制架构: Master-Slaves: 90%的场合都是这种一个master,多个slave的架构模式.主要用于读压力比较大的应用.对于对于数据实时性要求不是过高的系统,只要经过廉价的pcserver就能够扩展slave的数量.将读压力分散到多台slave机器上.架构图: w repl r client---> master -----> slave <----client |---> salve <----client |---> salve <----client dualmaster 复制架构: 为了解决主机down机,从机迅速切换成主机的架构方式. 实际上就是两个MySQLServer 互相将对方做为本身的Master,本身做为对方的Slave来进行复制。这样,任何一方所作的变动,都会经过复制应用到另一方的数据库中。 不会形成循环复制:在MySQL的BinaryLog 中记录了当前MySQL的server-id,并且这个参数也是咱们搭建MySQLReplication 的时候必须明确指定,并且Master和Slave的server-id参数值比须要不一致才能使MySQLReplication搭建成功 r/w client------> master | | REPL (相互) | r/w client------> master 经过DualMaster 复制架构,咱们不只可以避免由于正常的常规维护操做须要的停机所带来的从新搭建Replication环境的操做.Dual Master 复制架构和一些第三方的HA管理软件结合,还能够在咱们当前正在使用的Master出现异常没法提供服务以后,很是迅速的自动切换另一端来提供相应的服务,减小异常状况下带来的停机时间,而且彻底不须要人工干预。 搭建成一个DualMaster环境,并非为了让两端都提供写的服务。在正常状况下,咱们都只会将其中一端开启写服务,另一端仅仅只是提供读服务,或者彻底不提供任何服务,仅仅只是做为一个备用的机器存在。 级联复制架构(Master- Slaves - Slaves: 在某些场合读的压力特别大,一个master可能须要10台或者更多的slave才鞥支撑住读的压力.这样的话,master的压力比较大,由于光是slave的io线程就比较多,这样写的压力稍微大一点,就容易形成复制的延时. 解决==> 以利用MySQL能够在Slave端记录复制所产生变动的BinaryLog 信息的功能,也就是打开—log-slave-update选项。而后,经过二级(或者是更多级别)复制来减小Master端由于复制所带来的压力。 w repl repl client--->master -----> slave -----------> slave | repl |-->slave ----------> slave |repl |------> slave 全部的slave都是对客户只读 风险:级联过多,容易产生延时较长. dualmaster 与级联复制结合: w repl repl client--->master <------> master ----------> slave |repl |-------->slave |repl |-------->slave 最大的好处就是既能够避免主Master的写入操做不会受到Slave集群的复制所带来的影响,同时主Master须要切换的时候也基本上不会出现重搭Replication的状况. 搭建实现: 1.Master端准备工做 在搭建Replication环境以前,首先要保证Master端MySQL记录BinaryLog 的选项打开.使用log-bin[=pathfor binary log]参数选项。 还须要准备一个用于复制的MySQL用户。 mysql>CREATEUSER 'repl'@'192.168.0.2' ->IDENTIFIED BY 'password'; mysql>GRANTREPLICATION SLAVE ON *.* ->TO 'repl'@'192.168.0.2'; 2.获取Master端的备份“快照” 快照:全部数据均是基于某一特定时刻的,数据完整性和一致性均可以获得保证的备份集.同时还须要取得该备份集时刻所对应的Master端BinaryLog 的准确LogPosition,由于在后面配置Slave的时候会用到 方法: a)经过数据库全库冷备份: 冷备份. 如在Master刚刚启动以后,尚未应用程序链接上Master以前,经过执行SHOWMaster STATUS 命令从Master端获取到咱们能够使用的LogPosition。若是咱们没法在Master启动以后控制应用程序的链接,那么可能在咱们尚未来得及执行SHOWMaster STATUS 命令以前就已经有数据写进来了,这时候咱们能够经过mysqlbinlog客户端程序分析Master最新的一个BinaryLog 来获取其第一个有效的LogPosition。 b)经过LVM或者ZFS等具备snapshot功能的软件进行"热备份" 文件系统运行在LVM上面,那么咱们均可以经过相关的命令对MySQL的数据文件和日志文件所在的目录就作一个Snapshot,这样就能够获得了一个基本和全库冷备差很少的备份集。为了保证咱们的备份集数据可以完整且一致,咱们须要在进行Snapshot过程当中经过相关命令(FLUSHTABLES WITH READ LOCK)来锁住全部表的写操做,在作完Snapshot以后,咱们就能够UNLOCKTABLES 了 由于加了锁,因此更容易得到logposition : SHOW MASTER STATUS c)mysqldump 客户端程序 若是不能停机冷备份,并且也没有运行在b)上的文件系统,就须要使用mysqldump客户端程序. 能够锁定表(不支持事务,FLUSH TABLES WITH READ LOCK), 或者—single-transaction选项(支持事务)来保持数据的完整性. 得到logposition: 使用mysqldump的 --master-data d)经过现有某一个Slave端进行“热备份” 若是如今已经有Slave从咱们须要搭建Replication环境的Master上进行复制的话,那咱们这个备份集就很是容易取得了。。咱们能够暂时性的停掉现有Slave(若是有多台则仅仅只须要中止其中的一台).同时执行一次FLUSHTABLES 命令来刷新全部表和索引的数据。这时候在该Slave上面就不会再有任何的写入操做了,咱们既能够经过copy全部的数据文件和日志文件来作一个全备份,同时也能够经过Snapshot(若是支持)来进行备份。 经过现有Slave来获取备份集的方式,不只仅获得数据库备份的方式很简单,连所须要LogPosition,甚至是新Slave后期的配置等相关动做均可以省略掉,只须要新的Slave彻底基于这个备份集来启动,就能够正常从Master进行复制了。 整个过程当中咱们仅仅只是在必定时间内中止了某台现有Slave的复制线程,对系统的正常服务影响很小,因此这种方式也基本能够称之为“热备份”。 3.Slave端恢复"快照" a)恢复全库冷备份集 因为这个备份集是一个完整的数据库物理备份,咱们仅仅只须要将这个备份集经过FTP或者是SCP之类的网络传输软件复制到Slave所在的主机,根据Slave上my.cnf配置文件的设置,将文件存放在相应的目录,覆盖现有全部的数据和日志等相关文件,而后再启动Slave端的MySQL,就完成了整个恢复过程。 b)恢复对Master进行Snapshot获得的备份集 对于经过对Master进行Snapshot所获得的备份集,实际上和全库冷备的恢复方法基本同样,惟一的差异只是首先须要将该Snapshot经过相应的文件系统mount到某个目录下,而后才能进行后续的文件拷贝操做。以后的相关操做和恢复全库冷备份集基本一致,就再也不累述。 c)恢复mysqldump获得的备份集 经过mysqldump客户端程序所获得的备份集,和前面两种备份集的恢复方式有较大的差异。由于前面两种备份集的都属于物理备份,而经过mysqldump客户端程序所作的备份属于逻辑备份。恢复mysqldump备份集的方式是经过mysql客户端程序来执行备份文件中的全部SQL语句。 恢复以前,注销掉CHANGEMASTER TO 命令部分, d)恢复经过现有Slave所获得的热备份 经过现有Slave所获得的备份集和上面第一种或者第二种备份集也差很少。若是是经过直接拷贝数据和日志文件所获得的备份集,那么就和全库冷备同样的备份方式,若是是经过Snapshot获得的备份集,就和第二种备份恢复方式彻底一致。 4.配置并启动Slave: 经过CHANGEMASTER TO 命令来配置而后再启动Slave root@localhost: mysql 08:32:38> CHANGE MASTER TO ->MASTER_HOST='192.168.0.1', ->MASTER_USER='repl', ->MASTER_PASSWORD='password', ->MASTER_LOG_FILE='mysql-bin.000035', ->MASTER_LOG_POS=399; root@localhost: mysql 08:33:49> START SLAVE; 成功! replication的限制: 一旦数据库过于庞大,尤为是当写入过于频繁,很难由一台主机支撑的时候,咱们仍是会面临到扩展瓶颈。 数据切分(sharding):经过某种特定的条件,将咱们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。。数据的切分同时还能够提升系统的整体可用性,由于单台设备Crash以后,只有整体数据的某部分不可用,而不是全部的数据。 数据的切分(Sharding)模式: 一种是按照不一样的表(或者Schema)来切分到不一样的数据库(主机)之上,这种切能够称之为数据的垂直(纵向)切分; 另一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。 垂直切分: 一个架构设计较好的应用系统,其整体功能确定是由不少个功能模块所组成的,而每个功能模块所须要的数据对应到数据库中就是一个或者多个表。而在架构设计中,各个功能模块相互之间的交互点越统一越少,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好。这样的系统,实现数据的垂直切分也就越容易。 通常来讲,若是是一个负载相对不是很大的系统,并且表关联又很是的频繁,那可能数据库让步,将几个相关模块合并在一块儿减小应用程序的工做的方案能够减小较多的工做量,这是一个可行的方案。 一个垂直拆分的例子: 1.用户模块表:user,user_profile,user_group,user_photo_album 2.群组讨论表:groups,group_message,group_message_content,top_message 3.相册相关表:photo,photo_album,photo_album_relation,photo_comment 4.事件信息表:event 拆分: ◆群组讨论模块和用户模块之间主要存在经过用户或者是群组关系来进行关联。通常关联的时候都会是经过用户的id或者nick_name以及group的id来进行关联,经过模块之间的接口实现不会带来太多麻烦; ◆相册模块仅仅与用户模块存在经过用户的关联。这两个模块之间的关联基本就有经过用户id关联的内容,简单清晰,接口明确; ◆ 事件模块与各个模块可能都有关联,可是都只关注其各个模块中对象的ID信息,一样能够作到很容易分拆。 app====> [users]database ====>[group message]database ====>[photto albums]database ====>[events]database 因此,经过拆分,把之前的一个db存储这些表,分红了4个db写入,这样就减轻了压力. 垂直切分的优势 ◆ 数据库的拆分简单明了,拆分规则明确; ◆ 应用程序模块清晰明确,整合容易; ◆ 数据维护方便易行,容易定位; 垂直切分的缺点 ◆ 部分表关联没法在数据库级别完成,须要在程序中完成; ◆ 对于访问极其频繁且数据量超大的表仍然存在性能瓶颈,不必定能知足要求; ◆ 事务处理相对更为复杂; ◆ 切分达到必定程度以后,扩展性会遇到限制; ◆ 过读切分可能会带来系统过渡复杂而难以维护。 水平切分 将某个访问极其频繁的表再按照某个字段的某种规则来分散到多个表之中,每一个表中包含一部分数据。 对于上面的例子: 全部数据都是和用户关联的,那么咱们就能够根据用户来进行水平拆分,将不一样用户的数据切分到不一样的数据库中。 如今互联网很是火爆的Web2.0类型的网站,基本上大部分数据都可以经过会员用户信息关联上,可能不少核心表都很是适合经过会员ID来进行数据的水平切分。而像论坛社区讨论系统,就更容易切分了,很是容易按照论坛编号来进行数据的水平切分。切分以后基本上不会出现各个库之间的交互。 水平切分的优势 ◆ 表关联基本可以在数据库端所有完成; ◆ 不会存在某些超大型数据量和高负载的表遇到瓶颈的问题; ◆ 应用程序端总体架构改动相对较少; ◆ 事务处理相对简单; ◆ 只要切分规则可以定义好,基本上较难遇到扩展性限制; 水平切分的缺点 ◆ 切分规则相对更为复杂,很难抽象出一个可以知足整个数据库的切分规则; ◆ 后期数据的维护难度有所增长,人为手工定位数据更困难; ◆ 应用系统各模块耦合度较高,可能会对后面数据的迁移拆分形成必定的困难。 两种切分结合用: 通常来讲,咱们数据库中的全部表很难经过某一个(或少数几个)字段所有关联起来,因此很难简单的仅仅经过数据的水平切分来解决全部问题。而垂直切分也只能解决部分问题,对于那些负载很是高的系统,即便仅仅只是单个表都没法经过单台数据库主机来承担其负载。咱们必须结合“垂直”和“水平”两种切分方式同时使用 每个应用系统的负载都是一步一步增加上来的,在开始遇到性能瓶颈的时候,大多数架构师和DBA都会选择先进行数据的垂直拆分,由于这样的成本最早,最符合这个时期所追求的最大投入产出比。然而,随着业务的不断扩张,系统负载的持续增加,在系统稳定一段时期以后,通过了垂直拆分以后的数据库集群可能又再一次不堪重负,遇到了性能瓶颈。 ==>若是咱们再一次像最开始那样继续细分模块,进行数据的垂直切分,那咱们可能在不久的未来,又会遇到如今所面对的一样的问题。并且随着模块的不断的细化,应用系统的架构也会愈来愈复杂,整个系统极可能会出现失控的局面。 ==>这时候咱们就必需要经过数据的水平切分的优点,来解决这里所遇到的问题。并且,咱们彻底没必要要在使用数据水平切分的时候,推倒以前进行数据垂直切分的成果,而是在其基础上利用水平切分的优点来避开垂直切分的弊端,解决系统复杂性不断扩大的问题。而水平拆分的弊端(规则难以统一)也已经被以前的垂直切分解决掉了,让水平拆分能够进行的驾轻就熟。 示例数据库: 假设在最开始,咱们进行了数据的垂直切分,然而随着业务的不断增加,数据库系统遇到了瓶颈,咱们选择重构数据库集群的架构。如何重构?考虑到以前已经作好了数据的垂直切分,并且模块结构清晰明确。而业务增加的势头愈来愈猛,即便如今进一步再次拆分模块,也坚持不了过久。 ==>选择了在垂直切分的基础上再进行水平拆分。 ==>在经历过垂直拆分后的各个数据库集群中的每个都只有一个功能模块,而每一个功能模块中的全部表基本上都会与某个字段进行关联。如用户模块所有均可以经过用户ID进行切分,群组讨论模块则都经过群组ID来切分,相册模块则根据相册ID来进切分,最后的事件通知信息表考虑到数据的时限性(仅仅只会访问最近某个事件段的信息),则考虑按时间来切分。 数据切分以及整合方案. 数据库中的数据在通过垂直和(或)水平切分被存放在不一样的数据库主机以后,应用系统面临的最大问题就是如何来让这些数据源获得较好的整合 存在两种解决思路: 1.在每一个应用程序模块中配置管理本身须要的一个(或者多个)数据源,直接访问各个数据库,在模块内完成数据的整合; 2.经过中间代理层来统一管理全部的数据源,后端数据库集群对前端应用程序透明; 第二种方案,虽然内须要付出的成本可能会相对更大一些,可是对整个系统的扩展性来讲,是很是有帮助的。 针对第二种方案: 1.利用MySQLProxy 实现数据切分及整合. 可用来监视、分析或者传输他们之间的通信信息。他的灵活性容许你最大限度的使用它,目前具有的功能主要有链接路由,Query分析,Query过滤和修改,负载均衡,以及基本的HA机制等。 MySQLProxy 自己并不具备上述全部的这些功能,而是提供了实现上述功能的基础。要实现这些功能,还须要经过咱们自行编写LUA脚原本实现。 原理: MySQLProxy 其实是在客户端请求与MySQLServer 之间创建了一个链接池。全部客户端请求都是发向MySQLProxy,而后经由MySQLProxy 进行相应的分析,判断出是读操做仍是写操做,分发至对应的MySQLServer 上。对于多节点Slave集群,也能够起作到负载均衡的效果。 2.利用Amoeba实现数据切分及整合 Amoeba是一个基于Java开发的,专一于解决分布式数据库数据源整合Proxy程序的开源框架 Amoeba已经具备Query路由,Query过滤,读写分离,负载均衡以及HA机制等相关内容。 Amoeba主要解决的如下几个问题: a)数据切分后复杂数据源整合; b)提供数据切分规则并下降数据切分规则给数据库带来的影响; c)下降数据库与客户端的链接数; d)读写分离路由; AmoebaFor MySQL 主要是专门针对MySQL数据库的解决方案,前端应用程序请求的协议以及后端链接的数据源数据库都必须是MySQL。对于客户端的任何应用程序来讲,AmoebaForMySQL 和一个MySQL数据库没有什么区别,任何使用MySQL协议的客户端请求,均可以被AmoebaFor MySQL 解析并进行相应的处理。 AmoebaFor MySQL 的使用很是简单,全部的配置文件都是标准的XML文件,总共有四个配置文件。分别为: ◆ amoeba.xml:主配置文件,配置全部数据源以及Amoeba自身的参数设置; ◆ rule.xml:配置全部Query路由规则的信息; ◆ functionMap.xml:配置用于解析Query中的函数所对应的Java实现类; ◆rullFunctionMap.xml:配置路由规则中须要使用到的特定函数的实现类; Proxy程序经常使用的功能如读写分离,负载均衡等配置都在amoeba.xml中进行。Amoeba已经支持了实现数据的垂直切分和水平切分的自动路由,路由规则能够在rule.xml进行设置。 3.利用HiveDB实现数据切分及整合 HiveDB一样是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架,只是目前的HiveDB仅仅支持数据的水平切分。主要解决大数据量下数据库的扩展性及数据的高性能访问问题,同时支持数据的冗余及基本的HA机制。 HiveDB的实现机制与MySQLProxy 和Amoeba有必定的差别,他并非借助MySQL的Replication功能来实现数据的冗余,而是自行实现了数据冗余机制,而其底层主要是基于HibernateShards 来实现的数据切分工做。 数据切分与整合中可能存在的问题 ◆ 引入分布式事务的问题; ◆ 跨节点Join的问题; ◆ 跨节点合并排序分页问题; 引入分布式事务的问题? 一旦数据进行切分被分别存放在多个MySQLServer中以后,无论咱们的切分规则设计的多么的完美(实际上并不存在完美的切分规则),均可能形成以前的某些事务所涉及到的数据已经不在同一个MySQLServer 中了。 ==>将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并经过应用程序来总控各个小事务。 跨节点Join的问题? ==>先从一个节点取出数据,而后根据这些数据,再到另外一个表中取数据. ==>使用Federated存储引擎,问题是:乎若是远端的表结构发生了变动,本地的表定义信息是不会跟着发生相应变化的。 跨节点合并排序分页问题? ==>Join自己涉及到的多个表之间的数据读取通常都会存在一个顺序关系。可是排序分页就不太同样了,排序分页的数据源基本上能够说是一个表(或者一个结果集),自己并不存在一个顺序关系,因此在从多个数据源取数据的过程是彻底能够并行的。这样,排序分页数据的取数效率咱们能够作的比跨库Join更高,因此带来的性能损失相对的要更小。 分布式内存Cache软件Memcached: 1.做为提高系统性能的Cache工具: 若是咱们将Memcached做为应用系统的一个数据Cache服务,那么对于MySQL数据库来讲基本上不用作任何改造,仅仅经过应用程序本身来对这个Cache进行维护更新。这样做最大的好处就在于能够作到彻底不用动数据库相关的架构,可是同时也会有一个弊端,那就是若是须要Cache的数据对象较多的时候,应用程序所须要增长的代码量就会增长不少,同时系统复杂度以及维护成本也会直线上升。 架构图: appserver ---> ds proxy layer ---> db master --> db slave1 | |--> db slave2 | |---> memcached1 |---> memcached2 总体来看: 全部数据都会写入MySQLMaster 中,包括数据第一次写入时候的INSERT,同时也包括对已有数据的UPDATE和DELETE。 若是是对已经存在的数据,则须要在UPDATE或者DELETEMySQL 中数据的同时,删除Memcached中的数据,以此保证总体数据的一致性。 全部的读请求首先会发往Memcached中,若是读取到数据则直接返回,若是没有读取到数据,则再到MySQLSlaves 中读取数据,并将读取获得的数据写入到Memcached中进行Cache。 这种使用方式通常来讲比较适用于须要缓存对象类型少,而须要缓存的数据量又比较大的环境,是一个快速有效的彻底针对性能问题的解决方案。 2.和MySQL整合为数据服务层 有两种方式将Memcached和MySQL数据库整合成一个总体来对外提供数据服务: 直接利用Memcached的内存容量做为MySQL数据库的二级缓存,提高MySQLServer的缓存大小, 经过MySQL的UDF来和Memcached进行数据通讯,维护和更新Memcached中的数据,而应用端则直接经过Memcached来读取数据。 第一种方式,主要用于业务要求很是特殊,实在难以进行数据切分,并且有很难经过对应用程序进行改造利用上数据库以外的Cache的场景。 ==>经过开源项目WaffleGrid实现,将Memcached成功实现成为MySQL主机的外部“二级缓存”,目前仅支持用于Innodb的BufferPool。 架构图: appserver ---> ds proxy layer ---->Waffle Grid --->memcached1 |---> memcached2 |---> memcached3 |---> memcached4 |---> memcached5 这里面全部的memcached都是innodb的外部bufferpool, 而memcached和mysql之间必定要使用具备高带宽的私有网络. 第二种方案: 是经过MySQL所提供的UDF功能,自行编写相应的程序来实现MySQL与Memcached的数据通讯更新操做。 原理: 这种方式和WaffleGrid 不同的是Memcached中的数据并不彻底由MySQL来控制维护,而是由应用程序和MySQL一块儿来维护数据。每次应用程序从Memcached读取数据的时候,若是发现找不到本身须要的数据,则再转为从数据库中读取数据,而后将读取到的数据写入Memcached中。而MySQL则控制Memcached中数据的失效清理工做,每次数据库中有数据被更新或者被删除的时候,MySQL则经过用户自行编写的UDF(user define unction) 来调用Memcached的API来通知Memcached某些数据已经失效并删除该数据。 对于使用Memcached等感到成本高,能够考虑使用BerkeleyDB, TokyoTyrant 使用Search: 使用搜索引擎来提供全文检索.主要是基于Lucene. 把数据库的数据经过应用程序调用Lucene的相关API写入,并利用Lucene建立好索引,而后就能够经过调用Lucene所提供的数据检索API获得须要访问的数据,并且能够进行全模糊匹配 虽然Lucene的数据也是存放在磁盘上而不是内存中,可是因为高效的分词算法和索引结构,其效率也是很是的好。。看到不少网友在网上讨论,当数据量稍微大一些如几十个G以后Lucene的效率会降低的很是快,其实这是不科学的说法,就从我亲眼所见的场景中,就有好几百G的数据在Lucene中,性能仍然很出色。这几年性能优化的工做经历及经验中我有一个很深的体会,那就是一个软件性能的好坏,实际上并不只仅只由其自己所决定,不少时候一个很是高效的软件不一样的人使用会有大相径庭效果。因此,不少时候当咱们使用的第三方软件性能出现问题的时候,不要急着下结论认为是这个软件的问题,更多的是先从自身找找看咱们是否真的正确使用了他。 除了使用第三方的Search软件如Lucene以外,咱们也能够自行研发更适用于咱们自身应用场景的Search软件。好比:自行研发了一套纯内存存储的更适合于自身应用场景的高性能分布式Search软件 自行实现Cache服务: 若是目前的第三方软件已经基本解决了咱们系统当前遇到的80%以上的问题,可能就须要考虑是否有必要彻底自主研发了。 利用分布式用分布式并行计算实现大数据量的高性能运算: MapReduce(任务分解和任务合并功能)+ HDFS(分布式文件系统)+ Hbase(高性能的分布式数据库) 任何设备(或服务),只要是单点,就存在着很大的安全隐患。由于一旦这台设备(或服务)crash以后,在必定时间内就很难有备用设备(或服务)来顶替其功能。因此稍微重要一些的服务器或者应用系统,都会存在至少一个备份以供出现异常的时候可以很快的顶替上来提供服务。 对于数据库来讲,主备配置是很是常见的设计思路。而对于MySQL来讲,其Replication功能在实际应用中被普遍的用来实现主备配置的功能。 常规的Master- Slave 解决基本的主备设计: 在普通的一个Master后面复制一个或者多个Slave的架构设计中,当咱们的某一台Slave出现故障不能提供服务以后,咱们还有至少一台MySQL服务器(Master)能够提供服务,不至于全部和数据库相关的业务都不能运行下去。若是Slave超过一台,那么剩下的Slave也仍然可以不受任何干扰的继续提供服务。 这种架构方式很容易解决Slave出现故障的状况,并且不须要进行任何调整就能继续提供服务。 Master单点问题的解决: 两种解决方案: a)将Slave中的某一台切换成Master对外提供服务,同时将其余全部的Slave都以经过CHANGEMASTER 命令来将经过新的Master进行复制。 b)新增一台Master,也就是DualMaster 的解决方案。 c)方案最大的一个弊端就是切换步骤比较多,实现比较复杂。并且,在Master出现故障crash的那个时刻,咱们的全部Slave的复制进度并不必定彻底一致,有可能有少许的差别。这时候,选择哪个Slave做为Master也是一个比较头疼的问题。因此这个方案的可控性并非特别的高。 b)方案实际上就是经过DualMaster 来解决Master单点问题 经过两台MySQLServer 搭建成DualMaster 环境,正常状况下,全部客户端的Write请求都写往MasterA,而后经过Replication将MasterA 复制到MasterB。一旦MasterA 出现问题以后,全部的Write请求都转向MasterB。而在正常状况下,当MasterB 出现问题的时候,实际上不管是数据库仍是客户端的请求,都不会受到实质性的影响。 当咱们的MasterA 出现问题的时候,应用如何作到自动将请求转向到MasterB 呢? ==>只须要经过相应的硬件设备如F5或者Cluster管理软件如Heartbeat来设置一个VIP,正常状况下该VIP指向MasterA,而一旦MasterA 出现异常crash以后,则自动切换指向到MasterB,前端所的应用都经过这个VIP来访问Master。 DualMaster 与级联复制结合解决异常故障下的高可用: 经过前面的架构分析,咱们分别获得了Slave出现故障后的解决方案,也解决了Master的单点问题。如今咱们再经过DualMaster 与级联复制结合的架构,来获得一个总体的解决方案,解决系统总体可靠性的问题。 首先考虑Slave出现异常的状况。 在这个架构中,Slave出现异常后的处理状况和普通的Master- Slave 架构的处理方式彻底同样,仅仅须要在应用访问Slave集群的访问配置中去掉一个Slave节点便可解决,不管是经过应用程序本身判断,仍是经过硬件解决方案如F5均可以很容易的实现。 当MasterA 出现故障crash以后,MasterA 与MasterB 之间的复制将中断,全部客户端向MasterA 的Write请求都必须转向MasterB。这个转向动做的实现,能够经过上面介绍的第二中方案中所介绍的经过VIP的方式实现。因为以前全部的Slave就都是从MasterB 来实现复制,因此Slave集群不会受到任何的影响,客户端的全部Read请求也就不会受到任何的影响,整个过程能够彻底自动进行,不须要任何的人为干预。不过这里有一个隐患就是当MasterA crash 的时候若是MasterB 做为Slave的IO线程若是尚未读取完MasterA 的二进制日志的话,就会出现数据丢失的问题。要彻底解决这个问题,咱们只能经过第三方patch(google开发)来镜像MySQL的二进制日志到MasterB上面,才能彻底避免不丢失任何数据。 那么当MasterB 出现故障crash以后的状况又如何呢? 首先能够肯定的是咱们的全部Write请求都不会受到任何影响,并且全部的Read请求也都仍是可以正常访问。但全部Slave的复制都会中断,Slave上面的数据会开始出现滞后的现象。这时候咱们须要作的就是将全部的Slave进行CHANGEMASTER TO 操做,改成从MasterA 进行复制。因为全部Slave的复制都不可能超前最初的数据源,因此能够根据Slave上面的RelayLog中的时间戳信息与MasterA 中的时间戳信息进行对照来找到准确的复制起始点,不会形成任何的数据丢失。 DualMaster 与级联复制结合解决在线DDL变动问题: 使用DualMaster 加级联复制的组合架构的时候,对于MySQL的一个致命伤也就是在线DDL变动来讲,也能够获得必定的解决。如当咱们须要给某个表tab增长一个字段,能够经过以下在上述架构中来实现: 一、在Slave集群中抽出一台暂时中止提供服务,而后对其进行变动,完成后再放回集群继续提供服务; 二、重复第一步的操做完成全部Slave的变动; 三、暂停MasterB 的复制,同时关闭当前session记录二进制日志的功能,对其进行变动,完成后再启动复制; 四、经过VIP切换,将应用全部对MasterA 的请求切换至MasterB; 五、关闭MasterA 当前session记录二进制日志的功能,而后进行变动; 六、最后再将VIP从MasterB 切换回MasterA,至此,全部变动完成。 变动过程当中有几点须要注意的: 一、整个Slave集群须要可以承受在少一台MySQL的时候仍然可以支撑全部业务; 二、Slave集群中增长或者减小一台MySQL的操做简单,可经过在线调整应用配置来实现; 三、DualMaster 之间的VIP切换简单,且切换时间较少,由于这个切换过程会形成必定时间段内应用没法访问Master数据库。 四、在变动MasterB 的时候,会出现必定时间段内Slave集群数据的延时,因此若是单台主机的变动时间较长的话,须要在业务量较低的凌晨进行变动。若是有必要,甚至可能须要变动MasterB 以前将全部Slave切换为以MasterB 做为Master。 使用DRBD保证数据的高可靠: 在MySQL的官方文档手册的HighAvailability and Scalability 这一章中将DRBD做为MySQL实现高可用性的一个很是重要的方式来介绍的。 DRBD其实就是经过网络来实现块设备的数据镜像同步的一款开源Cluster软件,也被俗称为网络RAID1。 DRBD介于文件系统与磁盘介质之间,经过捕获上层文件系统的全部IO操做,而后调用内核中的IO模块来读写底层的磁盘介质。当DRBD捕获到文件系统的写操做以后,会在进行本地的磁盘写操做的同时,以TCP/IP协议将,经过本地主机的网络设备(NIC)将IO传递至远程主机的网络设备。当远程主机的DRBD监听到传递过来的IO信息以后,会当即将该数据写入到该DRBD所维护的磁盘设备。至此,整个IO才作完成。 DRBD在处理远程数据写入的时候有三种复制模式(或者称为级别)能够选择,不一样的复制模式保证了远程数据写入的三种可靠性。三种级别的选择能够经过DRBD的通用配置部分的protocal。不一样的复制模式,其实是影响了一个IO完成所表明的实际含义。由于当咱们使用DRBD的时候,一个IO完成的标识(DRBD返回IO完成)是本地写入和远程写入这两个并发进程都返回完成标识。下面我来详细介绍一下这三种复制模式所表明的含义: ProtocolA:这种模式是可靠性最低的模式,并且是一个异步的模式。当咱们使用这个模式来配置的时候,写远程数据的进程将数据经过TCP/IP协议发送进入本地主机的TCPsendbuffer 中,即返回完成。 ProtocolB:这种模式相对于ProtocolA 来讲,可靠性要更高一些。由于写入远程的线程会等待网络信息传输完成,也就是数据已经被远程的DRBD接受到以后返回完成。 ProtocolC:ProtocolC 复制模式是真正彻底的同步复制模式,只有当远程的DRBD将数据彻底写入磁盘成功后,才会返回完成。 其余高可用方案: RaiDB:其全称为RedundantArrays of Inexpensive Databases。也就是经过Raid理念来管理数据库的数据 raiddb-0: sqlrequest --> raidb controller --> table 1 --> table 2 --> table 3 raiddb-1: sqlrequest --> raidb controller --> db full --> db full --> db full raiddb-2: sqlrequest --> raidb controller --> db full --> table 1 --> table 2 raiddb-0-1: sqlrequest --> raidb controller 0 --->raidb-1 controler -->table1 --> table1 --->raidb-1 controler --> table2 --> table2 --->raidb-1 controler --> table3 --> table3 raiddb-1-0: sqlrequest --> raidb controller 1 --> raidb controller 0 -->table 1 --> table 2 --> table 3 --> raidb controller 0 --> table 1 --> table 2 --> table 3 --> raidb controller 0 --> table 1 --> table 2 --> table 3 方案比较: 一、MySQLReplication 优点:部署简单,实施方便,维护也不复杂,是MySQL天生就支持的功能。且主备机之间切换方便,能够经过第三方软件或者自行编写简单的脚本便可自动完成主备切换。 劣势:若是Master主机硬件故障且没法恢复,则可能形成部分未传送到Slave端的数据丢失; 二、MySQLCluster 优点:可用性很是高,性能很是好。每一分数据至少在不一样主机上面存在一份拷贝,且冗余数据拷贝实时同步。 劣势:维护较为复杂,产品还比较新,存在部分bug,目前还不必定适用于比较核心的线上系统。 三、DRBD磁盘网络镜像方案 优点:软件功能强大,数据在底层快设备级别跨物理主机镜像,且可根据性能和可靠性要求配置不一样级别的同步。IO操做保持顺序,可知足数据库对数据一致性的苛刻要求。 劣势:非分布式文件系统环境没法支持镜像数据同时可见,性能和可靠性二者相互矛盾,没法适用于性能和可靠性要求都比较苛刻的环境。维护成本高于MySQLReplication。 一个通过高可用可扩展设计的MySQL数据库集群,若是没有一个足够精细足够强大的监控系统,一样可能会让以前在高可用设计方面所作的努力功亏一篑。 MySQL分布式集群的监控系统总体架构体系: mysqldb--->| mysqldb--->| |-->报警 mysqldb--->|---->信息采集 --->信息存储 --->|-->状态 mysqldb--->| |-->趋势 mysqldb--->| 信息采集: 通常来讲,较小规模的监控点能够采用轮询的方式主动采集数据,可是当监控点达到必定规模之后,轮询的主动采集方式可能就会遇到必定的性能瓶颈和信息延时问题,尤为是当须要采集的数据比较多的时候尤其突出。而若是要采用从各个MySQL节点进行被动的推送,则可能须要开发可以支持网络通讯的监控程序,使采集的信息可以顺利的到达信息分析模块以即时获得分析,成本会稍微高一些。 不管是采用主动仍是被动的方式来进行数据采集,咱们都须要在监控主机上面部署采集相关信息的程序或脚本,包括主机信息和数据库信息。 主机状态监控: ●网络通讯:网络通讯基本上能够说是最容易检测的了,基本上只须要经过网络ping就能够获知是否正常。 ●系统软硬件错误:系统软硬件错误,通常使用文本监控软件,如sec、logwatch等日志监控专用软件,经过配置相应的匹配规则,从日志文件中捕获知足条件的错误信息,再发送给信息分析模块。 ● 磁盘空间:对于磁盘空间的使用情况监控,咱们经过最简单的shell脚本就能够轻松搞定 ●内存使用:系统物理内存使用量的信息采集一样很是简单,只须要一个基本的系统命令“free”,就能够得到当前系统内存总量,剩余使用量,以及文件系统的buffer和cache二者使用量。 ●进程数量:系统进程总数,或者某个用户下的进程数,均可以经过“ps”命令通过简单的处理来得到。 数据库状态信息 服务端口(3306)服务端口状态的监控和主机网络链接的监控一样很是简单,只须要对3306端口进行telnet尝试便可。 mysqld和mysqld_safe进程:mysqld进程是MySQLServer 最核心的进程。mysqld进程crash或者出现异常,MySQLServer 基本上也就没法正常提供服务了。固然,若是咱们是经过mysqld_safe来启动MySQLServer,则mysqld_safe会帮助咱们来监控mysqld进程的状态,当mysqld进程crash以后,mysqld_safe会立刻帮助咱们重启mysqld进程。 Errorlog:Errorlog 的监控目的主要是即时检测MySQLServer 运行过程当中发生的各类错误,如链接异常,系统bug等。 复制状态:若是咱们的MySQL数据库环境使用了MySQLReplication,就必须增长对Slave复制状态的监控。对Slave的复制状态的监控包括对IO线程和SQL线程两者的运行状态的监控。固然,若是但愿可以监控Replication更多的信息,如两个线程各自运行的进度等,一样能够在Slave节点上执行相应命令轻松获得 sky@localhost: (none) 04:30:38> show slave status\G 性能状态监控: 系统load值:系统load所包含的最关键含义是CPU运行等待的数量, sky@sky:~$uptime 17:27:44up 4:12, 3 users, load average: 0.87, 0.66, 0.61 “loadaverage: 0.87, 0.66, 0.61”中的三个数字,分别表明了1秒、5秒和15秒的load平均值。 CPU使用率:最为经常使用的方法是使用命令top和vmstat来获取。 磁盘IO量:能够经过vmstat, iostat来获取 swap进出量:swap 的使用主要表现了系统在物理内存不够的状况下使用虚拟内存的状况。 free命令只能得到当前系统swap的整体使用量。若是但愿得到实时的swap使用变化,仍是得依赖vmstat来获得 网络流量:第三方软件如ifstat、iftop和nload 数据库性能状态: MySQL数据库的性能状态监控点很是之多,其中不少量都是咱们不能忽视的必须监控的量,且90%以上的内容能够在链接上MySQLServer 后执行“SHOW/*!50000 GLOBAL */STATUS” 以及“SHOW/*!50000 GLOBAL */ VARIABLES”的输出值得到。须要注意的是上述命令所得到状态值其实是累计值,因此若是要计算(单位/某个)时间段内的变化量还须要稍加处理,能够在附录中找到两个命令输出值的详细说明。下面看看几项须要重点关注的性能状态: QPS(每秒Query量): QPS= Questions(or Queries) / Seconds 获取所需状态变量值: SHOW/*!50000 GLOBAL */ STATUS LIKE 'Questions' SHOW/*!50000 GLOBAL */ STATUS LIKE 'Queries' TPS(每秒事务量):在MySQLServer 中并无直接事务计数器,咱们只能经过回滚和提交计数器来计算出系统的事务量。 TPS= (Com_commit + Com_rollback) / Seconds KeyBuffer 命中率:KeyBuffer 命中率表明了MyISAM类型表的索引的Cache命中率。该命中率的大小将直接影响MyISAM类型表的读写性能。 key_buffer_read_hits= (1 - Key_reads / Key_read_requests) * 100% key_buffer_write_hits=(1 - Key_writes / Key_write_requests) * 100% mysq>SHOW/*!50000 GLOBAL */ STATUS ->LIKE 'Key%'; ----------------------------------- |Key_read_requests | 10 | |Key_reads | 4 | |Key_write_requests | 0 | |Key_writes | 0 | +------------------------+-------+ InnodbBuffer 命中率: 这里InnodbBuffer 所指的是innodb_buffer_pool,也就是用来缓存Innodb类型表的数据和索引的内存空间。 innodb_buffer_read_hits=(1-Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests)* 100% mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Innodb_buffer_pool_read%'; |Innodb_buffer_pool_read_requests | 5367 | |Innodb_buffer_pool_reads | 507 | +-----------------------------------+-------+ QueryCache 命中率: Query_cache_hits=(Qcache_hits / (Qcache_hits + Qcache_inserts)) * 100% mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Qcache%'; |Qcache_hits | 0 | |Qcache_inserts | 0 | TableCache 状态量: 判断系统参数table_open_cache的设置是否合理。Open_tables与Opened_tables之间的比率太低,则表明TableCache 设置太小,我的认为该值处于80%左右比较合适。 mysql>SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Open%'; |Open_tables | 51 | Opened_tables| 61 | ThreadCache 命中率: ThreadCache 命中率可以直接反应出咱们的系统参数thread_cache_size设置的是否合理.一个合理的thread_cache_size参数可以节约大量建立新链接时所须要消耗的资源。 Thread_cache_hits= (1 - Threads_created / Connections) * 100% mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Thread%'; |Threads_created | 3 | mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Connections'; Connections| 11 | 锁定状态:锁定状态包括表锁和行锁两种 mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE '%lock%'; |Innodb_row_lock_current_waits | 0 | |Innodb_row_lock_time | 0 | |Innodb_row_lock_time_avg | 0 | |Innodb_row_lock_time_max | 0 | |Innodb_row_lock_waits | 0 | |Table_locks_immediate | 44 | |Table_locks_waited | 0 | 如当Table_locks_waited与Table_locks_immediate的比值较大,则说明咱们的表锁形成的阻塞比较严重 Innodb_row_lock_waits较大,则说明Innodb的行锁也比较严重,且影响了其余线程的正常处理 复制延时量:复制延时量将直接影响了Slave数据库处于不一致状态的时间。若是咱们是经过Slave来提供读服务,就不得不重视这个延时量。能够经过在Slave节点上执行“SHOWSLAVE STATUS”命令,取Seconds_Behind_Master项的值来了解Slave当前的延时量(单位:秒) Tmptable 情况: TmpTable 的情况主要是用于监控MySQL使用临时表的量是否过多,是否有临时表过大而不得不从内存中换出到磁盘文件上。 mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Created_tmp%'; Created_tmp_disk_tables| 1 | Created_tmp_tables | 46 | 从上面能够看出系统使用了46次临时表,其中有1次临时表比较大,没法在内存中完成,而不得不使用到磁盘文件 BinlogCache 使用情况:BinlogCache 用于存放还未写入磁盘的Binlog信息。 mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Binlog_cache%'; |Binlog_cache_disk_use | 0 | |Binlog_cache_use | 0 | 若是Binlog_cache_disk_use值不为0,则说明BinlogCache 大小可能不够 Innodb_log_waits量: Innodb_log_waits状态变量直接反应出InnodbLog Buffer 空间不足形成等待的次数。 mysql> SHOW /*!50000 GLOBAL*/ STATUS ->LIKE 'Innodb_log_waits'; Innodb_log_waits| 0 经常使用开源监控软件: RRDTool。RRDTool全称为RoundRobinDatabase Tool,也就是环状循环数据库工具 Nagios:Nagois 是一个很是著名的运行在Linux/Unix上的对IT设备或服务的运行状态进行监控的软件。 MRTG MRTG应该算是一款比较老牌的监控软件了,功能比较简单,最初是为了监控网络链路流量而产生的。 Cacti Cacti和Nagios最大的区别在于前者具备很是强大的数据采集、存储以及展示功能 |