LinuxEye - Linux系统教程

LinuxEye - Linux系统教程

当前位置: 主页 > 架构 >

使用HAProxy,PHP,Redis和MySQL轻松构建每周上亿请求Web站点

时间:2014-11-17 22:15来源:oschina 编辑:linuxeye 点击:
数据: 服务器: 3x 应用节点 2x MySQL + 1x 用于备份 2x Redis 应用程序: 应用程序每周处理1,000,000,000请求 单一Symfony2实例达到700req/s(工作日平均550req/s) 平均响应时间 - 30 毫秒 Varnish - 高于
数据:
  • 服务器:
    • 3x 应用节点
    • 2x MySQL + 1x 用于备份
    • 2x Redis
  • 应用程序:
    • 应用程序每周处理1,000,000,000请求
    • 单一Symfony2实例达到700req/s(工作日平均550req/s)
    • 平均响应时间 - 30 毫秒
    • Varnish - 高于12,000 req/s (在压力测试中达到)
  • 数据存储:
    • Redis - 160,000,000记录, 100 GB 的数据 (我们主要的数据存储库!),
    • MySQL - 300,000,000记录 - 300 GB (第三层缓存)
平台:


  • 监控:
    • Icinga
    • Collectd
  • 应用程序:
    • HAProxy with Keepalived
    • Varnish
    • PHP (PHP-FPM) with Symfony2 Framework
  • 数据存储:
    • MySQL (master-master) with HAProxy load balancing
    • Redis (master-slave)
背景
差不多一年前,我们的朋友带着一个难以解决的问题来到我们的办公室。他们正在运行一个快速增长的电子商务新兴公司,当时他们希望将其扩展到国际水平。

因为他们仍然是一个新兴的公司,提出的解决方案必须是高性价比的,而不是在下一个服务器上将钱用完。遗留系统一直采用标准的LAMP架构搭建,他们已经有一个强大的PHP开发团队。新技术的引进必须要精巧,不能是过于复杂的架构,并且能让他们现有工作人员进一步维护此平台。

系统体系结构必须被设计为可扩展的方式,来实现扩展到下一个市场的计划。所以我们只好来了,检查他们的基础设施

以前的系统是以整体方式设计的。具体来说是一些独立的基于PHP的Web应用程序(在新兴公司有很多所谓的前端网站)。他们中的大多数都使用单一的数据库,他们共享一些常见的代码来处理业务逻辑。

进一步维护这样的应用可能是一个噩梦。由于部分代码已经被复制,更改一个网站,可能会导致业务逻辑的不一致 - 他们总是需要在所有的web应用程序中进行相同的更改。

此外,从项目管理的观点来看这也是一个问题 - 谁应该负责被分散在多个代码库的“那一部分”代码呢?

由于应用并没有完全耗尽单一Redis服务器的所有性能,因此从属服务器主要用于备份以及保持(系统)高可用性。一旦主服务器宕机,我们可以轻松地将应用转换到从属服务器上。进行维护工作或者迁移服务器时,复制也是很便利的-服务器的切换非常简单。

你可能疑惑为什么我们的Redis经常处于最大内存状态中。大多数的主键是永久类型的-大约占主键空间的90%。而其余的主键则完全是缓存,我们可以设置他们为TTL(译者注:Time-To-Live)过期。现在,主键空间被分为了两大部分:一部分是拥有TTL设置的(缓存)和另一部分没有TTL设置的(永久数据)。幸亏Redis设置的最大内存策略为“volatile-lru"(译者注:Redis的六种内存策略之一,表示只对设置了过期时间的key进行lru),那些最少使用的缓存主键(也只有这些设置了过期)将被自动删除。(译者注:应该是the least recently used...)

那样的话,我们就可以将单个Redis实例既可以当主要存储使用,也可以当典型缓存使用。

使用这一模型时,必须谨记的是要监测“过期”主键的数量。(译者注:以下为命令行查看部分)

db.redis1:6379> info keyspace

# Keyspace

db0:keys=16XXXXXXX,expires=11XXXXXX,avg_ttl=0

当你发现(“过期”主键)数量接近危险值0时,就需要启动切分或者提高内存了;-)

我们如何监视它呢?Icinga检查能够监视”过期“数量是否达到了崩溃点。我们也使用Redis曲线实现”失去主键“比的可视化。


一年之后,我可以说我们已经完全融入了Redis。从这个项目开始,Redis就没有让我们失望过——没有过停机也没有其他事件。

MySQL
除了Redis,我们还使用了传统的MySQL数据库。不同的是,我们只用它来做为第三方的缓存层。我们用它来存储哪些会占用Redis太多内存的,在近期不会使用的内容,这样我们就可以把它放在其他的硬盘上。这并不是什么新奇的技术,我们希望能够保持堆栈越简单越好,以便于维护。

我们有两个以上的MySQL服务器,配置为: Xeon E5-1620@3.60GHz, 64GB RAM, SSD。其中有本机异步主-主复制。以及一台单独的从节点用于备份。

MySQL的高可用性
从物理结构图上你可以看出,在每个MySQL框上有HAProxy,并实现了热备。通过HAProxy实现与MySQL的连接。

在每个数据库服务器上安装HAProxy的模式可以确保栈的高可靠性,并且不用为了负载均衡再则更加一台服务器。

HAProxy采用主动-被动模式(同一时间只有一个运行)运行。热备机制可以控制他们的可用性。在热备的控制下有一个浮点IP(VIP),它可以检查主负载均衡节点的可用性。当主节点崩溃时,第二(从属)HAProxy节点就会接管这个IP。

可扩展性
数据库通常是一个应用中最大的瓶颈。一般地,没有必要进行向外扩展操作——此次,我们通过增大Redis和MySQL空间来进行纵向扩展。虽然Redis运行在拥有128GB内存的服务器上,还有剩余空间——(但是)将他们迁移到拥有256GB内存的节点上是可行的。当然大容量也会给一些操作带来不便,比如快照或者运行服务器——启动Redis服务器将花费更长的时间。

纵向扩展之后,我们进行(横向)外部扩展。可喜的是,我们已经为我们的数据准备好了简单的分割结构。

Redis中我们有4”重“记录类型。记录可以根据数据类型被分到四个服务器中。我们不想根据哈希进行分割,而更乐于根据记录的类型进行分割。这种方式使得我们仍然可以使用通常对一类主键表现良好的MGET。

在MySQL中,数据表采用便于向不同服务器迁移的结构进行村粗——这些数据表也是基于记录类型(存储的)。

在分析完根据数据类型分割数据的优势后, 我们来看看哈希。

经验教训
  • 不要共享你的数据库  - 曾经,有一个前端网站想要将其会话处理转换到Redis。他们就连接到了我们的数据库上。这使得我们的Redis缓存空间被用尽,我们的应用也被拒绝存储缓存主键。所有的缓存开始只存储到MySQL服务器上,这导致MySQL服务器的系统开销过大。
  • 要有详细的日志 - 当没有足够的日志信息时,你就不能很快的调试出哪里出了问题。有一次,由于缺少某个信息,我们找不到产生这个问题的原因,不得不等该问题再一次出现(在增加了需要的日志信息后)。
  • 使用复杂架构并不意味着会“降低网站(速度)” - 有些人可能会对使用全栈架构来处理每秒如此数量的请求感到惊讶。这全在于你(如何)巧妙地使用你拥有的那些工具——即使在Node.js上你也能运行的很慢。选择一个能够提供良好开发环境的技术,而不是去对着不友好的工具进行抱怨(降低开发的士气)。

谁是背后的应用程序
通过波兰的软件公司Octivi设计的平台。 我们专心于可伸缩的结构体系,把焦点集中于性能和实用性。我们还要致谢来自客户端侧的IT部门。

相关文章 原文:http://www.oschina.net/translate/the-easy-way-of-building-a-growing-startup-architecture

转载请保留固定链接: http://www.linuxeye.com/architecture/2032.html

------分隔线----------------------------
标签:HAproxyRedisMySLphp
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
栏目列表
推荐内容