可扩展性
直接连接
2.修改应用的配置
还有一个分发负载的办法是重新配置应用。例如,你可以配置多个机器来分担生成大报表操作的负载。每台机器可以配置成连接到不同的MySQL备库,并为第N个用户或网站生成报表。
这样的系统很容易实现,但如果需要修改一些代码——包括配置文件修改——会变得脆弱且难以处理。硬编码有着固有的限制,需要在每台机器上修改硬编码,或者在一个中心服务器上修改,然后通过文件副本或代码控制更新命令"发布"到其他服务器上,如果将配置存储在服务器或缓存中,就可以避免这些麻烦。
3.修改DNS名
这是一个比较粗糙的负载均衡技术,但对于一些简单的应用,为不同的目的创建DNS还是很实用的。你可以为不同的服务器指定一个合适的名字。最简单的方法是只读服务器有一个NDS名,而给负责写操作的服务器起另外一个DNS名。如果备库能够跟上主库,那就把只读DNS名指定给备库,当出现延迟时,再将该DNS名指定给主库。这种DNS技术非常容易实现,但也有很多缺点。最大的问题是无法完全控制DNS.
- 1.修改DNS并不是立刻生效的,也不是原子的。将DNS的变化传递到整个网络或在网络间传播都需要比较长的时间
- 2.DNS数据会在各个地方缓存下来,它的过期时间是建议性质的,而非强制的
- 3.可能需要应用或服务器重启才能使修改后的DNS完全生效。
- 4.多个IP共用一个DNS名依赖于轮询行为来均衡请求,这并不是一个好主意,因为轮询行为并不宗总是可预知的
- 5.DBA可能没有权限直接访问DNS
除非应用非常简单,否则依赖不受控制的系统会非常危险。你可以通过修改/etc/hosts/文件而非DNS来改善对系统的控制。当发布一个对该文件的更新时,会知道该变更已经生效。这比等待缓存的DNS失效要好得多。但这仍然不是理想的办法。通常建议人们构建一个完全不依赖DNS的应用。即使应用很简单也适用,因为你无法预知应用会增长到多大规模。
4.转移IP地址
一些负载均衡解决方案依赖于在服务器间转移虚拟地址(虚拟IP地址不是直接连接到任何特定的计算机或网络端口,而是"漂浮"在计算机之间),一般能够很好地工作。这听起来和修改DNS很像,但完全时两码事。服务器不会根据DNS名去监听网络流量,而是根据指定的IP地址去见挺流量,所以转移IP地址允许DNS名保持不变。你可以通过ARP(地址解析协议)命令强制IP地址的更改快速而且原子性地通知到网络上。看过的适用最普遍的技术时Pacemaker,这是Linux-HA享目的Heartbeat工具的继承者。你可以适用单个IP地址,为其分配一个角色,例如read-only,当需要在机器间转移IP地址时,它能够感知到。其他的类似的工具包括LVS和Wackamole.
一个比较方便的技术时为每个物理服务器分配一个固定的IP地址。该IP地址固定在服务器上,不再改变。然后可以为每个逻辑上的"服务"使用一个虚拟IP地址。它们能够很方便地在服务器间转移,这使得转移服务和应用实例无须再重新配置应用,因此更加容易。即使不怎么经常转移IP地址,这也是一个很好地特性。
引入中间件
迄今为止,我们所讨论的方案都嘉定应用跟MySQL服务器使直接相连的。但是许多负载均衡解决方案都会引入一个中间件,作为网络通信的代理。它以便接受所有的通信请求,另一边将这些请求派发到指定的服务器上,然后把执行结果发送回请求的机器上。中间件可以实硬件设备或时软件(你可以把诸如LVS这样的解决方案配置成只有一个用需要创建一个新连接时才参与进来,此后不再作为中间价)。如图描述了这种架构,这种解决方案通常能工作得很好,当然除非为负载均衡器本身增加冗余,这样才能避免单点故障引起的整个系统瘫痪。从开源软件,如HAProxy,到许多广为人知的商业系统,有许多负载均衡器得到了成功的应用
1.负载均衡器
在市场上有许多负载均衡硬件和软件,但很少有专门为MySQL服务器设计的(MySQL Proxy是个例外,但目前还未能证明能够很好地工作,因为它会带来一些问题,例如延迟增加以及可扩展性瓶颈)。Web服务器通常更需要负载均衡,因此许多多用途的负载均衡设备都会支持HTTP,而对其他用途则只有一些很少的基本特性。MySQL连接都只是正常的TCP/IP连接,所以可以在MySQL上适用多用途负载均衡器。但由于缺少MySQL专有的特性,因此回多一些限制。
- 1.除非负载均衡器知道MySQL的真实负载,否则在分发请求时可能无法做到很好的负载均衡。不是所有的请求都是等同的,但多用途负载均衡器通常对所有的请求一视同仁。
- 2.许多负载均衡器知道如何检查一个HTTP请求并把会话"固定"到一个服务器上以保护在Web服务器上的会话状态。MySQL连接也是有状态的,但负载均衡器可能并不知道如何把所有从单个HTTP会话发送的连接请求"固定"到一个MySQL服务器上,这回损失一部分效率(如果单个会话的请求都是发到同一个MySQL服务器,服务器的缓存会更优效率)
- 3.连接池和长连接可能会阻碍负载均衡器分发连接请求。例如,一个连接池打开了预先配置好的连接数,负载均衡器在已有的四个MySQL服务器上分发这些连接。现在增加了两个以上的MySQL服务器。由于连接池不会请求新连接,因而新的服务器会一直空闲着。池中的连接会在服务器间不公平地分配负载,导致一些服务器超出负载,一些则几乎没有负载。可以在多个层面为连接设置失效时间来缓解这个问题,但这很复杂并且很难做到。连接池方案只有它们本身能够处理负载均衡时才能工作得很好。
- 4.许多多用途负载均衡器只会针对HTTP服务器做健康和负载检查。一个简单的负载均衡器最少能够核实服务器在一个TCP端口上接受的连接数。更好的负载均衡器能够自动发起一个HTTP请求,并检查返回值以确定这个Web服务器是否正常运转。MySQL并不接受3306端口的HTTP,因此需要自己来构建健康检查方法。你可以在MySQL服务器上安装一个HTTP服务器如那件,并将负载均衡器指向一个脚本,这个脚本检查MySQL服务器的状态并返回一个对应的状态值(实际上,如果能编码实现一个监听80端口的程序,或者配置xinetd来调用程序,甚至不需要再安装一个Web服务器)。最重要的时检查操作系统负载(通过查看/proc/loadavg)、复制状态,以及MySQL的连接数。
2.负载均衡算法
有许都算法用来决定哪个服务器接受下一个连接。每个厂商都有各自不同的算法,下面这个清单列出了一些可用的方法:
- 1.随机
负载均衡器随机地从可用的服务器池中选择一个服务器来处理请求 - 2.轮询
负载均衡器以循环顺序发送请求到服务器,例如:A,B,C,A,B,C - 3.最少连接数
下一个连接请求分配给拥有最少活跃连接的服务器 - 4.最快响应
能够最快处理请求的服务器接受下一个连接。当服务器池里同时存在快速和慢速服务器时,这很有小。即使同样的查询在不同的场景下运行也会有不同的表现,例如当查询结果已经缓存在查询缓存中,或者服务器缓存中已经包含了所需要的数据时 - 5.哈希
负载均衡器通过连接的源IP地址进行哈希,将其映射到池中的同一个服务器上。每次从同一个IP地址发起请求,负载均衡器都会将请求发送给同样的服务器。只有当池中服务器数目改变时这种绑定才会发生变化 - 6.权重
负载均衡器能够结合适用上述几种算法。例如,你可能拥有单CPU核双CPU的机器。双CPU机器有接近两倍的性能,所以可以让负载均衡器分派两倍的请求给双CPU机器
哪种算法最优取决于具体的工作负载。例如最少连接算法,如果有新机器加入,可能会有大量连接涌入该服务器,而这时候它的缓存还没有包含热数据。你需要通过测试来为你的工作负载找到最好的性能。除了正常的日常运转,还需要考虑极端情况。在比较极端的情况下——例如负载升高,修改模式,或者多台服务器下线——至少要避免系统出现重大错误。我们这里只描述了即时处理请求的算法,无须对连接请求排队。但有时候适用排队算法可能更有效。例如,一个算法可能只维护给定的数据库服务器并发数目,同一时刻只允许不超过N个活跃事务。如果有太多的活跃事务,就将新的请求放到一个队列里,然后让可用服务器列表的第一个来处理它。有些连接池也支持队列算法
3.在服务器池中增加/移除服务器
增加一个服务器到池中并不是简单地插入禁区,然后通知负载均衡器就可以了,你可能以为只要不是一下子涌进大量连接请求就可以了,但并不一定如此。有时候你会缓慢增加一台服务器的负载,但一些缓存还是"冷"的服务器可能会慢到一段时间内都无法处理任何的用户请求。如果用户浏览一个页面需要30秒才能返回数据,即使流量很小,这个服务器也是不可用的。有一个方法可以避免这个问题,在通知负载均衡器有新服务器加入前,可以暂时把SELECT查询映射到一台活跃服务器上,然后再新开启的服务器上读取和重放活跃服务器上的日志文件,或者捕捉生产服务器上的网络通信,并重放它的一部分查询。Percona Toolkit中的pt-query-digest工具能够有所帮助。另一个有效的办法是适用Percona Server或MySQL5.6的快速预热特性。
在配置连接池中的服务器时,要保证有足够多未使用的容量,以备在撤下服务器做维护时适用,或者当服务求失效时可以派上用场。每台服务器上都应该保留高于"足够’的容量。
要确保配置的限制值足够高,即使从池中撤出一些服务器也能够工作。举个例子,如果你发现每个MySQL服务器一般有100个连接,应该设置池中每个服务器的max_connections值为200.这样就算一半的服务器失效,服务器池也能处理同样数量的请求