热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从小流量到高并发:开发者眼中的LNMP架构

本篇从单台机器架构开始,然后会遇到了哪些瓶颈,哪些坑,如何解决等,是一个典型的LNMP架构网站的架构演变。希望对大家有价值。

本篇从单台机器架构开始,然后会遇到了哪些瓶颈,哪些坑,如何解决等,是一个典型的LNMP架构网站的架构演变。希望对大家有价值。

  有一天,我突发奇想创建了一个站点,基于 LNMP 架构,起初只有我自己访问,后来因为我点儿正,访问量越来越大,所以最终导致下面说的架构演变。

  单台机器

  单台机器因为只是一个小网站,访问量一天也没有多少UV(100以内),所以用一台1核1G内存的机器就够了。机器上安装的是 CentOS 系统,然后搭建了 nginx+php-fpm+mysql 的环境。

  两台机器

  

  访问量越来越大,日UV突破5000,单台机器不够了,本可以增加机器配置编程4核8G,但是考虑到还要换机器,所以直接添置一台数据库服务器单独跑 MySQL服务。

  原来的服务器只需要跑 Nginx+PHP-FPM,新加服务器跑 MySQL 服务。 在这里,往往会遇到一个问题,就是如何在多台机器上编译安装 LNMP 环境,在单台机器上编译都没有问题,PHP 放在最后,因为它依赖 MySQL,但我们这里需要把 MySQL 放到另一台机器,所以编译肯定会报错。解决这个问题,其实很简单,即使 Web上不需要 MySQL,我们也要安装一下,因为编译 PHP 的时候依赖它。

  增加memcached

  

  访问量持续增加,UV上万了,DB 服务器和 WEB 服务器压力越来越大,这时候我们需要加一个缓存来缓解 DB 服务器的压力。同样是两台机器,只不过 Web机器配置需要升级了,原来的1核1G内存不够用了,不仅要加 CPU 还要加内存,因为在 Web 上我们需要运行 memcached 服务,同时 PHP 也需要安装memcache 扩展。

  增加Web服务器,MySQL主从分布

  访问量又扩大了,UV到了5W,数据库服务器因为一开始配置就挺高,所以没有压力,但是 Web 服务器负载有点高了,在高峰期可以感觉到网站访问变慢。所以,这时候不得不考虑要加一台 Web 服务器。另外,数据库是单点,如果磁盘损坏,可能会带来意想不到的后果,所以我们有必要加一台从 DB 服务器,作为数据备份用。

  

  在这里,两台 Web 服务器并没有做负载均衡。主要是为了节省资源,暂时先不去购买服务器做负载均衡。

  我们使用 DNS 轮询的方法来把用户的请求分发到两台机器上,但这种该架构有个问题,一旦一台 Web 机器宕机,将会有一半的用户访问不到业务。

  还有一个问题,我们也需要考虑到,如何保证 Web 服务器上的数据一致,比如用户可能会上传图片到 Web 服务器上,假如他上传到了 Web1 上,那 WEB2 是不存在这个图片的。所以我们需要做一个共享存储让 Web1 和 Web2 同时可以访问,所以在这里我把 WEB1 的一个目录使用 NFS 共享出来,让 Web2 去挂载。

  还有一个问题就是memcached服务如何分配,在这里,我是把 memcaced 服务分别安装到两台 Web 上的,自己用自己的 memcached 服务。

  MySQL读写分离

  访问量持续上升,UV已到了数十万。网站在高峰期总是会卡顿那么一段时间。经排查,发现在 MySQL 服务器上有很多慢查询,经过各种调优依然没有太明显效果,最后决定做读写分离。

  做读写分离有两种方案,第一可以借助程序来实现,把所有的写操作指向到主 MySQL ,所有的读操作指向到从 MySQL。对于这种方案,机器数量和环境不用做任何调整,唯一要做的是程序代码要改一下。第二可以借助 mysql-proxy 来实现,不用修改代码,节省开发成本,但需要增加一个角色。架构是这样的,如下图:

  

  负载均衡

  两台 Web 服务器因为有一台配置比较老,因此在高峰期时,终究是没有能扛住而挂掉。结果影响了一半的用户访问不到网站了,这就是所谓的单点故障。经过此次事故,我又开始修改架构,尽量避免单点故障,在 Web 前端设置了负载均衡设备,并且做了高可用。

  

  在这里我拿 Nginx 做了负载均衡器,并没有使用 LVS和HAProxy,我觉得 Nginx 更容易操作,更好控制。

  为了节省成本,我并没有单独把 mysql-proxy 摘出来作为独立服务器,因为那样的话,也得为它考虑单点问题。在这个架构中,其实还有一个缺陷,就是 NFS 服务端也是有风险的,更加保险的做法是单独搞一台服务器做NFS服务。

  继续扩展

  UV上升到100万,两台 Web 服务器明显不够用了,而瓶颈并不在 MySQL 上。所以,只增加 Web,同时把 NFS 服务器单独摘出来,并做一个备用 NFS 服务器。

  

  引入NoSQL

  UV近1000万,三台 Web 服务器也早已不够,增加到5台。而 MySQL 服务器压力逐渐变大,针对 MySQL 的慢查询,发现压力主要体现在个别 SQL 语句上,该优化的已经优化到极致,对于这几个查询,其实是可以使用 NoSQL 的。

  于是,我找懂PHP开发的朋友修改了程序,把一些访问量大的数据存储到Redis,从而减少了对 MySQL 服务器的压力。 而 Redis 为了防止单点也做了主从。

  

  MySQL架构演变

  假设一个网站(Discuz)从最开始访问量很小做到日PV千万,我们来推测一下它的MySQL服务器架构演变过程。

  第一阶段

  网站访问量日PV量级在1W以下。单台机器跑Web和DB,不需要做架构层调优(比如,不需要增加memcached缓存)。此时,数据往往都是每日冷备份的,但有时候如果考虑数据安全性,会搭建一个MySQL主从。

  第二阶段

  网站访问量日PV达到几万。此时单台机器已经有点负载,需要我们把Web和DB分开,需要搭建memcached服务作为缓存。也就是说,在这个阶段,我们还可以使用单台机器跑mysql去承担整个网站的数据存储和查询。如果做 MySQL 主从,目的也是为了数据安全性。

  第三阶段

  网站访问量日PV达到几十万。单台机器虽然也可以支撑,但是需要的机器配置要比之前的机器好很多。

  如果经费允许,可以购买配置很高的机器来跑mysql服务,但是并不是说,配置翻倍,性能也翻倍,到了一定阶段配置增加已经不能带来性能的增加。

  所以,此阶段,我们会想到做MySQL服务的集群,也就是说我们可以拿多台机器跑MySQL。但是,MySQL集群和Web集群是不一样的,我们需要考虑数据的一致性,所以不能简单套用做Web集群的方式(lvs,nginx代理)。

  可以做的架构是,MySQL主从,一主多从。为了保证架构的健壮和数据完整,主只能是一个,从可以是多个。

  还有一个问题,我们需要想到,就是在前端Web层,我们的程序里面指定了MySQL机器的ip,那么当机器有多台时,程序里面如何去配置?Discuz其实有一个功能,支持MySQL读写分离。即我们可以拿多台机器跑MySQL,其中一台写,其他多台是读,我们只需要把读和写的 IP 分别配置到程序中,程序自动会去区分机器。当然,如果不使用 discuz 自带的配置,我们还可以引用一个软件叫做 mysql-proxy, 使用他来实现读写分离。它支持一主多从的模式。

  第四阶段

  网站访问量日PV到几百万。之前的一主多从模式已经遇到瓶颈,因为当网站访问量变大,读数据库的量也会越来越大,我们需要多加一些从进来,但是从的数量增加到数十台时,由于主需要把bin-log全部分发到所有从上,那么这个过程本身就是一件很繁琐的事情,再加上频繁读取,势必会造成从上同步过来的数据有很大延迟。

  所以,我们可以做一个优化,把MySQL原来的一主多从变为一主一从,然后从作为其他从的主,而前面的主只负责网站业务的写入,而后面的从不负责网站任何业务,只负责给其他从同步bin-log。这样还可以继续多叠加几个从库。

  第五阶段

  网站访问量日PV到1千万的时候,我们发现,网站的写入量非常大,我们之前架构中只有一个主,这里的主已经成为瓶颈了。所以,需要再近一步做出调整。比如,我们可以把业务分模块,把用户相关的单独分离出来,把权限、积分等也可以分离出来单独跑一个库,然后再做主从,也就是所谓的分库。

  当然也可以换一个维度,把访问量或者写入量大的表单独分离出来,跑在一台服务器上,也可以把一个表分成多个小表。这一步操作,涉及到一些程序上的改动,所以需要事先和开发同事做好沟通和设计。

  总之,这一步要做的就是分库分表。

  小结

  再往后发展,继续把大表分小表即可。 比如阿里淘宝网站的数据量是巨量的,他们的数据库全部都是 MySQL,他们的 MySQL 架构就是遵循分库分表这个原则的,只不过他们划分规则会有很多维度,比如可以根据地域划分,可以根据买家、卖家划分,可以根据时间划分等。


推荐阅读
  • 本文介绍了数据库体系的基础知识,涵盖关系型数据库(如MySQL)和非关系型数据库(如MongoDB)的基本操作及高级功能。通过三个阶段的学习路径——基础、优化和部署,帮助读者全面掌握数据库的使用和管理。 ... [详细]
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • Spring Cloud因其强大的功能和灵活性,被誉为开发分布式系统的‘一站式’解决方案。它不仅简化了分布式系统中的常见模式实现,还被广泛应用于企业级生产环境中。本书内容详实,覆盖了从微服务基础到Spring Cloud的高级应用,适合各层次的开发者。 ... [详细]
  • 免费获取:全面更新的Linux集群视频教程及配套资源
    本资源包含最新的Linux集群视频教程、详细的教学资料、实用的学习课件、完整的源代码及多种软件开发工具。百度网盘链接:https://pan.baidu.com/s/1roYoSM0jHqa3PrCfaaaqUQ,提取码:41py。关注我们的公众号,获取更多更新的技术教程。 ... [详细]
  • 本文提供了一套实用的方法论,旨在帮助开发者构建能够应对高并发请求且易于扩展的Web服务。内容涵盖了服务器架构、数据库管理、缓存策略以及异步处理等多个方面。 ... [详细]
  • 一面问题:MySQLRedisKafka线程算法mysql知道哪些存储引擎,它们的区别mysql索引在什么情况下会失效mysql在项目中的优化场景&# ... [详细]
  • 腾讯视频 Node.js 服务国庆阅兵直播高并发实战
    本文分享了腾讯视频团队在国庆阅兵直播项目中,如何利用Node.js服务成功应对2.38亿次观看的高并发挑战。文章将从服务架构、可用性保障、缓存策略、日志与告警等方面详细解析。 ... [详细]
  • 微服务架构详解及其入门指南
    本文详细介绍了微服务的基本概念、发展历程、与传统架构的区别及优势,并探讨了适合采用微服务架构的场景。此外,文章还深入分析了几个主流的微服务开发框架,特别是Spring Cloud的组成和特点。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 探讨GET与POST请求数据传输的最大容量
    在Web开发领域,GET和POST是最常见的两种数据传输方法。本文将深入探讨这两种请求方式在不同环境下的数据传输能力及其限制。 ... [详细]
  • Kubernetes中构建Nginx Service的详细步骤
    本文介绍了如何在Kubernetes集群中通过创建Service来稳定访问Nginx应用的方法,包括Service的基本概念及其在Kubernetes中的作用。 ... [详细]
  • 本文档详细介绍了服务器与应用系统迁移的策略与实施步骤。迁移不仅涉及数据的转移,还包括环境配置、应用兼容性测试等多个方面,旨在确保迁移过程的顺利进行及迁移后的系统稳定运行。 ... [详细]
  • 成为一名高效的Java架构师不仅需要掌握高级Java编程技巧,还需深入理解JVM的工作原理及其优化方法。此外,对池技术(包括对象池、连接池和线程池)的应用、多线程处理、集合对象的内部机制、以及常用的数据结构和算法的精通也是必不可少的。同时,熟悉Linux操作系统、TCP/IP协议栈、HTTP协议等基础知识,对于构建高效稳定的系统同样重要。 ... [详细]
author-avatar
乖乖88918
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有