当前位置: 首页 > 后端技术 > Node.js

MySQL-Scalability3负载均衡:炫目迷人

时间:2023-04-03 22:47:11 Node.js

负载均衡的基本思想很简单:在一个服务器集群中尽可能地平均负载。基于这种思想,我们通常的做法是在服务器前设置一个负载均衡器。负载平衡器的作用是将请求的连接路由到最空闲的可用服务器。图1显示了一个大型Web负载平衡设置。其中一个负责HTTP流量,另一个负责MySQL访问。负载平衡有五个常见目的:可扩展性。负载均衡对于一些扩展很有帮助,比如读写分离时从备库读取数据。效率。负载平衡通过控制请求的路由位置来帮助更有效地使用资源。可用性。灵活的负载均衡方案可以大大提高服务的可用性。透明度。客户端不需要知道有没有负载均衡器,也不需要知道负载均衡器后面有多少台机器。呈现给客户端的是一个透明的服务器。一致性。如果应用程序是有状态的(数据库事务、网站会话等),那么负载均衡器可以将相关查询定向到同一台服务器以防止状态丢失。对于负载均衡的实现,一般有两种方式:直连和引入中间件。1直连有些人认为负载均衡是配置应用程序和MySQL服务器之间的直接东西,但实际上这并不是唯一的负载均衡方式。下面我们就来探讨一下应用直连的常用方法及相关注意事项。1.1复制的读写分离这种方式容易出现最大的问题之一:脏数据。一个典型的例子是当用户对博客文章发表评论时,然后重新加载页面而没有看到添加的评论。当然,我们不能因为脏数据的问题而放弃读写分离。其实对于很多应用来说,对于脏数据的容忍度可能是比较高的,这个时候可以大胆的引入这种方式。那么对于脏数据容忍度低的应用,如何实现读写分离呢?接下来我们进一步区分读写分离。我相信你总能找到适合你的策略。1)基于查询分离如果应用只有少量不能容忍脏数据的数据,我们可以把所有不能容忍脏数据的读写都分配给master。其他读取查询分配给奴隶。这种策略很容易实现,但是如果容忍脏数据的查询很少,很可能无法有效利用备库。2)基于脏数据的分离这是对基于查询的分离策略的一个小改进。需要做一些额外的工作,例如让应用程序检查复制延迟以确定备用数据是否是最新的。很多报表应用可以采用这种策略:只需要将夜间加载的数据复制到备库接口,而不关心主库是否完全跟上。3)基于会话的分离策略比脏数据分离策略更深入。判断用户是否修改了数据。用户不需要看到其他用户的最新数据,只需要看到自己的更新。具体的,可以在会话层设置一个标志位来表示用户是否有更新。一旦用户更新,用户的查询将被定向到主数据库一段时间。该策略很好地折衷了简单性和有效性,是更值得推荐的策略。当然,如果你有足够的想法,你可以将基于会话的分离策略与复制延迟监控策略结合起来。如果用户10秒前更新了数据,5秒内所有备库都延迟了,可以大胆的从备库读取数据。需要注意的是,记得整个会话选择同一个备库,否则一旦多个备库的延迟不一致,就会给用户带来麻烦。4)基于全局版本/会话分离,通过记录主库的日志坐标,对比备库的复制坐标,确认备库是否更新数据。当应用程序指向写操作时,事务提交后,执行一次SHOWMASTERSTATUS操作,然后将主库的日志坐标存储在缓存中,作为修改对象或会话的版本号。当应用程序连接到备库时,执行SHOWSLAVESTATUS,将备库上的坐标与缓存中的版本号进行比较。如果备库的记录点比主库的记录点新,说明备库中对应的数据已经更新,可以放心使用了。事实上,很多读写分离策略都需要通过监控复制延迟来决定读查询的分配。但是需要注意的是,通过SHOWSLAVESTATUS得到的Seconds_behind_master列的值并不能准确代表延迟。我们可以使用PerconaToolkit中的pt-heartbeat工具来更好地监控延迟。1.2修改DNS名称对于一些比较简单的应用,可以根据不同的目的创建DNS。最简单的方法是为只读服务器使用一个DNS名称(read.mysql-db.com),为写入服务器使用另一个DNS名称(write.mysql-db.com)。如果备库跟得上主库,则将只读DNS名称指向备库,否则指向主库。这个策略很容易实现,但是有一个很大的问题:你不能完全控制DNS。对DNS的更改既不是立即的也不是原子的。DNS更改需要很长时间才能传播到整个网络或在网络之间传播。DNS数据会被缓存在各个地方,其过期时间是推荐而非强制的。修改后的DNS可能需要重新启动应用程序或服务器才能完全生效。这种策略比较危险,即使可以通过修改/etc/hosts文件来避免无法完全控制DNS的问题,仍然是一种比较理想的策略。1.3转移IP地址通过在服务器之间转移虚拟地址,实现负载均衡。是不是感觉跟修改DNS差不多?但实际上这是完全不同的事情。传输IP地址可以让DNS名称保持不变,我们可以强制IP地址的变化通过ARP命令(不知道ARP,看这里)快速原子地通知局域网。一种更方便的技术是为每个物理服务器分配一个固定的IP地址。这个IP地址是固定在服务器上的,不会改变。然后可以为每个逻辑“服务”(可以理解为容器)使用一个虚拟IP地址。这样,无需重新配置应用程序,就可以轻松地在服务器之间传输IP,实施起来也更容易。2引入中间件以上策略都是假设应用连接到MySQL服务器,但是很多负载均衡都会引入一个中间件作为网络通信的代理。它一方面接受所有的通信,另一方面将这些请求分发到指定的服务器,并将执行结果返回给请求的机器。图2显示了此架构。2.1负载均衡器市面上有许多负载均衡硬件和软件,但很少有专门为MySQL服务器设计的。Web服务器通常需要更多的负载平衡,因此许多通用负载平衡设备都支持HTTP,并且几乎没有其他用途的基本功能。MySQL连接只是普通的TCP/IP连接,因此可以将多用途负载平衡器与MySQL一起使用。但是由于缺少MySQL特有的特性,会有更多的限制:分发请求可能无法达到很好的负载均衡。对MySQL会话的支持不足,它可能不知道如何“固定”从单个HTTP会话发送到MySQL服务器的所有连接请求。连接池和持久连接可以防止负载平衡器分发连接请求。没有做好MySQL服务器的健康和负载检查。2.2负载均衡算法有许多算法用于决定哪个服务器将接受下一个连接。每个厂家都有自己不同的算法,常见的有以下几种方法:随机分配。从可用服务器池中随机选择一个服务器来处理请求。轮询。以循环顺序向服务器发送请求,eg:A,B,C,A,B,C.hash。散列连接的源IP地址以将其映射到池中的同一服务器。最快的响应。将连接分配给可以最快处理请求的服务器。最小连接数。将连接分配给活动连接最少的服务器。重量。根据机器的性能等情况,为不同的机器配置不同的权重,让高性能的机器可以处理更多的连接。上面说的各种方法没有最好的,只有最合适的,要看具体的工作量。此外,我们只描述立即处理的算法。但有时使用排队算法可能更有效。例如,一种算法可能只维护给定的数据库服务器并发性,同时允许不超过N个活动事务。如果有太多活动事务,将新请求放入队列中,让可用服务器列表处理它们。2.3一主多备负载均衡最常见的复制结构是一主多备。这种架构的扩展性较差,但是我们可以通过一些方式结合负载均衡来达到更好的效果。职能部门。针对厂商的报表、分析、数据仓库、全文索引等功能,配置一个或一组备用数据库,扩展单一功能的容量。确保备用数据库与主数据库保持同步。备份的问题是脏数据。为此,我们可以使用函数MASTER_POS_WAIT()来阻塞主库的运行,直到备库赶上主库设置的同步点。或者,我们可以使用复制心跳来检查延迟。我们不能也不应该从应用的一开始就想着把架构做成阿里的架构。最好的方法是实施应用程序目前明确需要的内容,并提前计划可能的快速增长。此外,为可扩展性设定一个数字目标是有意义的,就像我们为性能、10K或100K并发设定一个精确目标一样。这样就可以避免诸如序列化或互操作性等开销问题通过相关理论带入我们的应用程序中。在MySQL的扩展策略上,当一个典型的应用增长到非常大的规模时,通常先从单机迁移到备库外扩架构,再进行数据分片或功能分区。这里需要注意的是,我们并不提倡“越早分片,越多分片”之类的建议。事实上,分片既复杂又昂贵,最重要的是,许多应用程序可能根本不需要它。与其在sharding上花大价钱,还不如看看新硬件和新版MySQL的变化。也许这些新变化会让你大吃一惊。总结直连重“分离”,均衡器和算法都有局限性。可扩展性的定量指标。