高可用性
避免单点失效
找到并消除系统中的可能失效的单点,并结合切换到备用组件的机制,这是一种通过减少恢复时间(MTTR)来改善可用性的方法。如果你够聪明,有时候甚至能将实际的恢复时间降低至0,但总的来说这很困难。(即使一些非常引人注目的技术,例如昂贵的负载均衡器,在发现问题并进行反馈时也会导致一定的延迟)。思考并梳理整个应用,尝试去定位任何可能失效的单点。是一个硬盘驱动器,一台服务器,一台交换或路由器,还是某个机架的电源?所有数据都在一个数据中心,或者冗余数据中心是由同一个公司提供的吗?系统中任何不冗余的部分都是一个可能失效的单点。其他比较普遍的单点失效依赖于一些服务,例如DNS,单一网络提供商(感觉太偏执了?检查你的冗余网络连接是不是真的连接到不同的互联网主干,确保它们的物理位置不在同一条街道或者同一个电线杆上,这样它们才不会被同一个挖土机或者汽车破坏掉)、单个云"可用区域",以及单个电力输送网,具体有哪些取决于你的关注点。
单点失效并不总是能够消除。增加冗余或许也无法做到,因为有些限制无法避免,例如地理位置,预算,或者时间限制等。试着去理解每一个影响可用性的部分,采取一种平衡的观点来看待风险,并首先解决其中影响最大的那个。一些人试图编写一个软件来处理所有的硬件失效,但软件本身导致的宕机时间可能比它节约的还要多。也有人想建立一种"永不沉没"的系统,包括各种冗余,但它们忘记了数据中心可能掉电或失去连接。或许它们彻底忘记了恶意攻击者和程序错误的可能性,这些情况可能会删除或损坏数据------一个不小心执行的DROP TABLE也会产生宕机时间.
可以采用两种方法来为系统增加冗余:增加空余容量和重复组件。增加容量余量通常很简单------可以使用前面讨论的任何技术。一个提升可用性的方法是创建一个集群或服务器池,并使用负载均衡解决方案。如果一台服务器失效,其他服务器可以接管它的负载。有些人有意识地不使用组建地全部能力,这样可以保留一些"动态余量"来处理因为负载增加或组件失效导致的性能问题。
处于很多方面的考虑会需要冗余组件,并在主要组件失效时能有一个备件来随时替换。冗余组件可以是空闲的网卡、路由器或者硬盘驱动器------任何能想到鞥多可能失效的东西。完全冗余MySQL服务器可能优点困难,因为一个服务器在没有数据时毫无用处。这意味着你必须确保备用服务器能够获得主服务器上的数据。共享或复制存储是一个比较流行的办法。但这真的是一个靠可用架构吗?让我们深入其中看看
共享存储或磁盘复制
共享存储能够为数据库服务器和存储解耦合,通常使用的是SAN.使用共享存储时,服务器能够正常挂载文件系统并进行操作。如果服务器挂了,备用服务器可以挂载相同的文件系统,执行需要的恢复操作,并在失效服务器的数据上启动MySQL.这个过程在逻辑上跟修复那台故障的服务器没什么两样,不过更快速,因为备用服务器已经启动,随时可以运行。当开始故障转移时,检查文件系统、恢复InnoDB以及预热(Percona Server提供了一个新特性,能够把buffer pool保存下来并在重启后还原,在使用共享存储时能够很好地工作。这可以减少几个小时甚至好几天的预热时间。MySQL5.6也有相似的特性。)是最有可能遇到延迟的地方,但检测失效本身在许多设置中也会花费很长时间。
共享存储有两个优点:可以避免除存储外的其他任何组件失效所引起的数据丢失,并为非存储组件建立冗余提供可能。因此它有助于减少系统一些部分的可用性需求,这样就可以集中精力关注一小部分组件来获得高可用性。不过,共享存储本身仍然是可能失效的单点。如果共享存储失效了,那整个系统也失效了,尽管SAN通常设计良好,但也可能失效,有时候需要特别关注,就算SAN本身拥有冗余也会失效。
共享存储本身也有风险,如果MySQL崩溃等故障导致数据文件损坏,可能会导致备用服务器无法恢复。我们强烈建议在使用共享存储策略时选择InnoDB存储引擎或其他稳定的ACID存储引擎。一次崩溃几乎肯定会损坏MyISAM表,需要花费很长时间来修复,并且会丢失数据。我们也强烈建议使用日志型文件系统。我们见过比较严重的情况是,使用非日志型文件系统和SAN(这是文件系统的问题,跟SAN无关)导致数据损坏无法恢复。
磁盘复制技术是另外一个获得跟SAN类似效果的方法。MySQL中最普遍使用的磁盘复制技术是DRBP,并结合Linux-HA享目中的工具使用。DRBD是一个以Linux内核模块方式实现的块级别同步复制技术。它通过网卡将主服务器的每个块复制到另外一个服务器上的块设备上(备用设备),并在主设备提交块之前记录下来(事实上可以调整DRBD的同步级别,将其设置成异步等待远程设备接收数据,或者在远程设备将数据写入磁盘前一直阻塞住。同样,强烈建议为DRBD专门使用一块网卡)。由于在备用DRBD设备上的写入必须要在主设备上的写入完成之前,因此备用设备的性能至少要和主设备一样,否则就会限制主设备的写入性能。同样,如果正在使用DRBD磁盘复制技术以保证在主设备失效时有一个可随时替换的备用设备,备用服务器的硬件应该跟主服务器的相匹配。带电池写缓存的RAID控制器对DRBD而言几乎是必需的,因为在没有这样的控制器时性能可能会很差。
如果主服务器失效,可以备用设备提升为主设备。因为DRBD是在磁盘块层进行复制,而文件系统也可能会不一致。这意味着最好是使用日志型文件系统来做快速恢复。一旦设备恢复完成,MySQL还需要运行自身的恢复。原故障服务器恢复后,会与新的主设备进行同步,并假定自身角色为备用设备。
从如何实际地实现故障转移的角度来看,DRBD和SAN很相似:有一个热备机器,开始提供服务时会使用和故障机器相同的数据,最大的不同时,DRBD是复制存储------不是共享存储------所以当使用DRBD时,获得的是一份复制的数据,而SAN则是使用与故障机器同一物理设备上的相同数副本。换句话说,磁盘复制技术的数据是冗余的,所以存储的数据本身都不会存在单点失效问题。这两种情况下,当启动备用机器时,MySQL服务器的缓存都是空的。相比之下,备库的缓存至少是部分预热的。
DRBD有一些很好的特性和功能,可以防止集群软件普遍会遇到的一些问题。一个典型的例子是"脑裂综合征",在两个节点同时提升自己为主服务器时会发生这种问题。可以通过配置DRBD来防止这种事情发生。但是DRBD也不是一个能满足所有需求的完美解决方案。我们来看看它有哪些缺点:
- 1.DRBD的故障转移无法做到秒级别以内。它通常需要至少几秒钟时间来将设备提升成主设备,这还不包括任何必要的文件系统恢复和MySQL恢复
- 2.它很昂贵,因为必需在主动------被动模式下运行。热备服务器的复制设备因为处于被动模式,无法用于其他任务。当然这不是缺点取决于看问题的角度。如果你希望获得真正的高可用性并且在发生故障时不能容忍服务降级,就不应该在一台机器上运行两台服务器的负载量,因为如果这么做了,当其中一台发生故障时,就无法处理这些负载了。可以用这些备用服务器做一些其他用途,例如用作备库,但还是会有一些资源浪费。
- 3.对于MyISAM表实际上用处不打,因为MyISAM表崩溃后需要花费很长时间来检查和修复。对任何期望获得高可用性的系统而言,MyISAM都不是一个好选择;请使用InnoDB或其他支持快速、安全恢复的存储引擎来代替MyISAM
- 4.DRBD无法代替备份。如果磁盘由于蓄意的破坏、误操作、Bug或者其他硬件故障导致数据损坏,DRBD将无济于事。此时复制的数据只是被损坏数据的完美副本。你需要使用备份(或MySQL延时复制)来避免这些问题。
- 5.对写操作而言增加了负担。具体会增加多少负担呢?通常可以使用百分比来表示,但这并不是一个好的度量方法。你需要理解写入时增加的延迟主要由网络往返开销和远程服务器存储导致,特别时对于小的写入而言延迟会更大。尽管增加的延迟可能也就0.3ms,这看起来比在本地磁盘上IO的4~10ms的延迟要小很多,但却是正常的带有写缓存的RAID控制器的延迟的3~4倍。使用DRBD导致服务器变慢最常见的原因时MySQL使用InnoDB并采取了完全持久化模式(这里的意思时Innodb_flush_log_at_trx_commit=1的情况)。这会导致许多小的写入和fsync()调用,通过DRBD同步时会非常慢
我们倾向于只使用DRBD复制存放二进制日志的设备。如果主动节点失效,可以在被动节点上开启一个日志服务器,然后对失效主库的所有备库一个用这些二进制日志。接下来可以选择其中一个备库提升为主库,以代替失效的系统。
说到底,共享存储和磁盘复制与其说是高可用性(低宕机时间)解决方案,不如说是一种保证数据安全的方法。只要拥有数据,就可以从故障中恢复,并且比无法恢复的情况的MTTR(平均恢复时间)更低(即使是很长的恢复时间也比不能恢复要快。)但是相比于备用服务器启动并一直运行的架构,大多数共享存储或磁盘复制架构会增加MTTR.有两种启用备用设备并运行的方法:MySQL的同步复制
主动------主动访问模式下的共享存储怎么样?
在一个SAN、NAS或者集群文件系统上以主动------主动模式运行多个实例怎么样?MySQL不能这么做。因为MySQL并没有被设计成和其他MySQL实例同步对数据的访问,所以无法在同一份数据上开启多个MySQL实例(如果在一份只读的静态数据上使用MyISAM,技术上是可行的,但还没有见过任何实际的应用)。MySQL 5.6.8之后,InnoDB也增加了一个只读模式,可以只读的方式用多个实例访问同一份只读数据文件。MySQL的一个名为ScaleDB的存储引擎在底层提供了操作共享存储的API,但还没有进行评估过,也没有见过忍耐和在生产环境使用。