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

by admin on 2019年9月3日

HAProxy、PHP、Redis和MySQL支撑10亿请求架构方案

图片 1

在公司的发展中,保证服务器的可扩展性对于扩大企业的市场需要具有重要作用,因此,这对架构师提出了一定的要求。Octivi联合创始人兼软件架构师Antoni
Orfin将向你介绍一个非常简单的架构,使用HAProxy、PHP、Redis和MySQL就能支撑每周10亿请求。同时,你还能了解项目未来的横向扩展途径及常见的模式。

以下为译文:

图片 2

在这篇文章中,我将展示一个非常简单的架构,使用HAProxy、PHP、Redis和MySQL支撑每周10亿请求。除此之外,我还将展示项目未来的横向扩展途径及常见的模式,下面我们一起看细节。

状态:

服务器:

3个应用程序节点2个MySQL+1个备份2个Redis

数据存储:

  1. Redis储存了1.6亿记录,数据体积大约100GB,同时它是我们的主要数据存储
  2. MySQL储存了3亿记录,数据体积大约300GB,通常情况下它作为三级缓存层

应用程序:

  1. 应用程序每周处理10亿请求
  2. 峰值700请求每秒的单Symfony2实例(平均工作日约550请求每秒)
  3. 平均响应时间30毫秒
  4. Varnish,每秒请求超过1.2万次(压力测试过程中获得)

  1. 平台:

图片 3

  • 监视:
  1. Icinga
  2. Collectd
  • 应用程序
  1. HAProxy + Keepalived
  2. Varnish
  3. PHP(PHP-FPM)+ Symfony2 Framework
  • 数据存储
  1. MySQL(主从配置),使用HAProxy做负载均衡
  2. Redis (主从配置)

案例是由Antoni
Orfin
写的客座文章,他是Octivi的联合创始人和软件架构师。

国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:
内部邀请码:C8E245J **(不写邀请码,没有现金送) 国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。 **

转载:

方案由从易到难的顺序,但无论哪种方法,都需要保证的是Reids和MySQL的数据一致性。

背景

大约1年前,一个朋友找到我并提出了一个苛刻的要求:它们是一个飞速发展的电子商务初创公司,而当时已经准备向国际发展。介于那个时候他们仍然是一个创业公司,初始解决方案必须符合所谓的成本效益,因此也就无法在服务器上投入更多的资金。遗留系统使用了标准的LAMP堆栈,因此他们拥有一个强力的PHP开发团队。如果必须引入新技术的话,那么这些技术必须足够简单,不会存在太多架构上的复杂性;那么,他们当下的技术团队就可以对应用进行长期的维护。

为了满足他们扩展到下一个市场的需求,架构师必须使用可扩展理念进行设计。首先,我们审视了他们的基础设施:

图片 4

图片 5

老系统使用了单模块化设计思路,底层是一些基于PHP的Web应用程序。这个初创公司有许多所谓的前端网站,它们大多都使用了独立的数据库,并共享了一些支撑业务逻辑的通用代码。毫不客气的说,长期维护这种应用程序绝对是一个噩梦:因为随着业务的发展,有些代码必须被重写,这样的话,修改某个网站将不可避免导致业务逻辑上的不一致,这样一来,他们不得不在所有Web应用程序上做相同的修改。

通常情况下,这该归结于项目管理问题,管理员必须对横跨多个代码库的那些代码负责。基于这个观点,整改第一步就是提取核心的业务关键功能,并将之拆分为独立的服务(这也是本文的一个重点部分),也就是所谓的面向服务架构,在整个系统内遵循“separation
of
concern”原则。每个服务只负责一个业务逻辑,同时也要明确更高等级的业务功能。举个形象的例子也就是,这个系统可能是个搜索引擎、一个销售系统等。

前端网站通过REST
API与服务交互,响应则基于JSON格式。为了简单起见,我们选择了SOAP,一个开发者比较无爱的协议,因为谁都不愿意解析一堆的XML。

提取一些不会经常处理的服务,比如身份验证和会话管理。这是非常必要的一个环节,因为它们的处理等级比较高。前端网站负责这个部分,只有它们可以识别用户。这样一来我们可以保持服务的足够简单,在处理扩展和代码相关问题时都具有巨大的优势,可谓各司其职,完美无缺。

带来的好处:

  • 独立子系统(服务)可以便捷的在不同团队中开发,开发者互不干涉,效率理所当然提升。
  • 身份验证和会话不会通过它们来管理,因此它们造成的扩展问题不翼而飞。
  • 业务逻辑被区分,不同的前端网站不会再存在功能冗余。
  • 显著地提高了服务的可用性。

共生的缺点:

为系统管理员带来更大的工作量。鉴于服务都使用了独立的基础设施,这将给管理员带来更多需要关注的地方。

很难保持向后兼容。在一年的维护之后,API方法中发生了数不尽的变化。因此问题发生了,它们必将破坏向后兼容,因为每个网站的代码都可能发生变化,还可能存在许多技术人员同时修改一个网站的情况……然而,一年后,所有方法匹配的仍然是项目开始时建立的文档。

英文原文:The Easy Way Of Building A
Growing Startup Architecture Using HAProxy, PHP, Redis And MySQL To
Ha…


方案一:

方案一:

应用程序层

图片 6

着眼请求工作流,第一层是应用程序。HAProxy负载均衡器、Varnish和Symfony2应用程序都在这一层。来自前端网站的请求首先会传递给HAProxy,随后负载均衡器将把他分给不同的节点。

应用程序节点配置

  • Xeon
    [email protected],64GB
    RAM,SATA
  • Varnish
  • Apache2
  • PHP 5.4.X(PHP-FPM),使用APC字节码缓存

我们购买了3个这样的服务器,N+1冗余配置的active-active模式,备份服务器同样处理请求。因为性能不是首要因素,我们为每个节点配置独立的Varnish以降低缓存hit,同时也避免了单点故障(SPOF)。在这个项目中,我们更重视可用性。因为一个前端网站服务器中使用了Apache
2,我们保留了这个堆栈。这样一来,管理员不会困扰于太多新加入的技术。

Symfony2应用程序

应用程序本身基于Symfony2建立,这是一个PHP全堆栈框架,提供了大量加速开发的组件。作为基于复杂框架的典型REST服务可能受到很多人质疑,这里为你细说:

  • 对 PHP/Symfony
    开发者友好。客户端IT团队由PHP开发者组成,添加新技术将意味必须招聘新的开发者,因为业务系统必须做长时间的维护。
  • 清晰的项目结构。PHP/Symfony虽然从来都不是必需品,但却是许多项目的默认选择。引入新的开发者将非常方便,因为对他们来说代码非常友好。
  • 许多现成的组件。遵循DRY思想……没有人愿意花力气去做重复的工作,我们也不例外。我们使用了大量的Symfony2
    Console
    Component,这个框架非常有利于做CLI命令,以及应用程序性能分析(debug工具栏)、记录器等。

在选用Symfony2之前,我们做了大量的性能测试以保证应用程序可以支撑计划流量。我们制定了概念验证,并使用JMeter执行,我们得到了让人满意的结果——每秒700请求时响应时间可以控制在50毫秒。这些测试给了我们足够的信心,让我们坚信,即使Symfony2这样复杂的框架也可以得到理想的性能。

应用程序分析与监控

我们使用Symfony2工具来监视应用程序,在收集指定方法执行时间上表现的非常不错,特别是那些与第三方网络服务交互的操作。这样一来,我们可以发现架构中潜在的弱点,找出应用程序中最耗时的部分。

冗长的日志同样是不可缺少的一部分,我们使用PHP
Monolog库把这些日志处理成优雅的log-lines,便于开发者和管理员理解。这里需要注意的是尽可能多地添加细节,越详细越好,我们使用了不同的日志等级:

  • Debug,可能会发生的事情。比如,请求信息在调用前会传送给一个外部Web服务;事情发生后从API调用响应。
  • Error,当错误发生时请求流并未被终止,比如第三方API的错误响应。
  • Critical,应用程序崩溃的瞬间。

因此,你可以清晰地了解Error和Critical信息。而在开发/测试环境中,Debug信息同样被记录。同时,日志被存储在不同的文件中,也就是Monolog库下的“channels”。系统中有一个主日志文件,记录了所有应用程序级错误,以及各个channel的短日志,从单独的文件中记录了来自各个channel的详细日志。

扩展性

扩展平台的应用程序层并不困难,HAProxy性能并不会在短时间耗尽,唯一需要考虑的就是如何冗余以避免单点故障。因此,当下需要做的只是添加下一个应用程序节点。

在文章中,我将向您展示我们开发的基于HAProxy,PHP,Redis和MySQL的非常简单的架构的方法,它可以无缝地处理约每周十亿次的请求。文章中还列举了进一步扩展它的可能途径,并指出了针对于该项目的不常见的模式。

 

程序同时写Redis和MySQL
读Redis

程序同时写Redis和MySQL
读Redis

数据层

我们使用Redis和MySQL存储所有的数据,MySQL更多作为三级缓存层,而Redis则是系统的主要数据存储。

Ubuntu
14.04下Redis安装及简单测试

http://www.linuxidc.com/Linux/2014-05/101544.htm

英文原文:The Easy Way Of Building A Growing Startup Architecture Using HAProxy, PHP, Redis And MySQL To Ha…

案例是由Antoni
Orfin
写的客座文章,他是Octivi的联合创始人和软件架构师。

在文章中,我将向您展示我们开发的基于HAProxy,PHP,Redis和MySQL的非常简单的架构的方法,它可以无缝地处理约每周十亿次的请求。文章中还列举了进一步扩展它的可能途径,并指出了针对于该项目的不常见的模式。

图片 7

图片 7

Redis

在系统设计时,我们基于以下几点来选择满足计划需求的数据库:

  • 在存储大量数据时不会影响性能,大约2.5亿记录
  • 通常情况下多是基于特定资源的简单GET请求,没有查找及复杂的SELECT操作
  • 在单请求时尽可能多的获得资源以降低延时

在经过一些调查后,我们决定使用Redis

  • 大部分我们执行的操作都具有 O(1)或O(N)复杂性,
    N是需要检索键的数量,这意味着keyspace大小并不会影响性能。
  • 通常情况下会使用MGET命令行同时检索100个以上的键,这样可以尽可能的避免网络延时,而不是在循环中做多重GET操作。

我们当下拥有两个Redis服务器,使用主从复制模式。这两个节点的配置相同,都是Xeon
[email protected],128GB,SSD。内存限制被设置为100GB,通常情况下使用率都是100%。

图片 9

在应用程序并没有耗尽单个Redis服务器的所有资源时,从节点主要作作备份使用,用以保证高有效性。如果主节点宕机,我们可以快速的将应用程序切换到从节点。在维护和服务器迁移时,复制同样被执行——转换一个服务器非常简单。

你可能会猜想当Redis资源被一直耗尽时的情景,所有的键都是持久化类型,大约占90%
keyspace,剩余资源被全部被用于TTL过期缓存。当下,keyspace已经被分为两个部分:一个是TTL集(缓存),另一个则是用于持久化数据。感谢“volatile-lru”最大化内存设置的可行性,最不经常使用缓存键会被移除。如此一来,系统就可以一直保持单Redis实例同时执行两个操作——主存储和通用缓存。

使用这个模式必须一直监视“期满”键的数量:

db.redis1:6379> info keyspace

# Keyspace

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

“期满”键数量越接近0情况越危险,这个时候管理员就需要考虑适当的分片或者是增加内存。

我们如何进行监控?这里使用Icinga
check,仪表盘会显示数字是否会达到临界点,我们还使用了Redis来可视化“丢失键”的比率。

图片 10

在一年后,我们已经爱上了Redis,它从未让我们失望,这一年系统从未发生任何宕机情况。

Redis集群明细文档
http://www.linuxidc.com/Linux/2013-09/90118.htm

数据:

服务器:

  • 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 (第三层缓存)

方案二:

方案二:

MySQL

在Redis之外,我们还使用了传统RDBMS——MySQL。但是区别于他人,我们通常使用它作为三级缓存层。我们使用MySQL存储一些不会经常使用对象以降低Redis的资源使用率,因此它们被放到了硬盘上。这里没有什么可说道的地方,我们只是尽可能地让其保持简单。我们使用了两个MySQL服务器,配置是Xeon
[email protected],64GB
RAM,SSD。两个服务器使用本地、异步的主-主复制。此外,我们使用一个单独的从节点作为备份。

MySQL的高可用性

在应用程序中,数据库永远是最难的瓶颈。当前,这里还不需要考虑横向扩展操作,我们多是纵向扩展Redis和MySQL服务器。当下这个策略还存在一定的发展空间,Redis运行在一个126GB内存的服务器上,扩展到256GB也并不困难。当然,这样的服务器也存在劣势,比如快照,又或是是简单的启动——Redis服务器启动需要很长的时间。

在纵向扩展失效后进行的必然是横向扩展,值得高兴的是,项目开始时我们就为数据准备了一个易于分片的结构:

在Redis中,我们为记录使用了4个“heavy”类型。基于数据类型,它们可以分片到4个服务器上。我们避免使用哈希分片,而是选择基于记录类型分片。这种情况下,我们仍然可以运行MGET,它始终在一种类型键上执行。

在MySQL上,结构化的表格非常易于向另一台服务器上迁移——同样基于记录类型(表格)。当然,一旦基于记录类型的分片不再奏效,我们将转移至哈希。

Ubuntu 12.10下安装Redis(图文详解)+ Jedis连接Redis
http://www.linuxidc.com/Linux/2013-06/85816.htm

平台:

程序写MySQL, 使用Gearman调用MySQL的UDF,完成对Redis的写
读Redis

程序写MySQL, 使用Gearman调用MySQL的UDF,完成对Redis的写
读Redis

学到的知识

  • 不要共享你的数据库。一旦一个前端网站期望切换会话处理到Redis,Redis缓存空间将被耗尽,同时它会拒绝应用程序保存下一个缓存键。这样一来所有的缓存将转至MySQL服务器,这将导致大量开销。
  • 日志越详细越好。如果log-lines中没有足够的信息,快速Debug问题定位将成为难点。如此一来,你不得不等待一个又一个问题发生,直到找到根结所在。
  • 架构中使用复杂的框架并不意味着低性能。许多人惊讶我们使用全堆栈框架来支撑如此流量应用程序,其秘诀在于更聪明的使用工具,否则即使是Node.js也可能变得很慢。选择一个提供良好开发环境的技术,没有人期望使用一堆不友好的工具,这将降低开发团队士气。

在公司的发展中,保证服务器的可扩展性对于扩大企业的市场需要具有重要作用,因此,这对…

Redis系列-安装部署维护篇
http://www.linuxidc.com/Linux/2012-12/75627.htm

图片 11

监控:

  • Icinga

  • Collectd

应用程序:

  • HAProxy with Keepalived

  • Varnish

  • PHP (PHP-FPM) with Symfony2 Framework

数据存储:

  • MySQL (master-master) with HAProxy load balancing

  • Redis (master-slave)

  • 背景

    差不多一年前,我们的朋友带着一个难以解决的问题来到我们的办公室。他们正在运行一个快速增长的电子商务新兴公司,当时他们希望将其扩展到国际水平。

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

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

    图片 12 图片 13 

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

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

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

  • 根据这一观察,我们的第一步是提取核心的关键业务功能到一个单独的服务中(这是本文的范围)。它是面向服务的架构模式。在整个系统范围内考虑“关注点分离”的原则。该服务是保持一种逻辑的,具体的更高级别的业务功能。给你一个真实的例子 –
    服务可以是一个搜索引擎,销售系统等。

    前端网站通过一个REST
    API
    来和服务进行通信。响应是基于JSON格式的。我们选择它的原因是简单性,相反SOAP始终对开发者来说比较困难(没有人喜欢分析XMLS…;-))

    提取的服务并不处理如身份验证和会话管理之类的东西。这是必须的,这些事情是在一个更高的层次来处理的。前端网站负责这一点,因为只有他们才能确定他们的用户。这样,我们将服务更简化 –
    在进一步扩展的问题和代码的东西上。没有什么不好的,因为它有不同的任务来处理。 

  • 优点:


    不同的子系统(服务)可以很容易被完全不同的开发团队开发。开发者之间可以互不干涉。

    – 不用处理用户授权和访问问题,因此就不存在常见的等级问题了。

    – 在一个地方维护业务逻辑-不同的前端网站之间不存在冗余的功能。

    – 易于该服务被大众所接受

    缺点:


    系统管理者的工作量更大- 因为服务是基于其自身的架构体系,所以系统管理员就需要对该架构增加关注。

    – 保持向后兼容性-在一年的维护中,API
    方法的改变多的会不计其数。 问题是这些改变千万不能破坏向后兼容性,不然每个前端网站的代码都需要修改,而且同时部署所有网站时会增加程序员工作…一年之后,所有的方法仍然能够与第一版的文档兼容。

  • 应用层

    图片 14

    根据请求流,第一层是应用层,应用层里面包括HAProxy负载均衡器,Varnish和Symfony2
    网络应用。来自前端网站的请求首先到达HAProxy,然后通过HAProxy分发到应用节点中。

    应用节点配置

    • Xeon E5-1620@3.60GHz, 64GB RAM, SATA

    • Varnish

    • Apache2

    • PHP 5.4.X running as PHP-FPM, with APC bytecode cache

    我们已经拥有三个这样的应用服务器。它是双活模式下的N+1模式 –
    ”备份“服务器主动处理请求。

    保持Varnish在每个节点中的独立性使得快取命中率更低,但是这种方式下我们就不存在SPOF问题(一个节点失效,全部系统停止运转)。我们这样做的目的是考虑可用性高于性能(在我们的案例中性能不是问题)。

    我们选择Apache2,它也被用在前端网站服务器中。避免混合进许多技术使得系统管理员的维护更加容易。

  • Symfony2 应用

    应用本身是建立在Symfony2的顶层之上。它是一个完全PHP的栈框架,提供丰富的有用组件,这些组件能够加速开发的进程。将典型的REST服务建立在一个复杂的框架之上可能对某些人来说不可思议,让我对其中的原因进行说明:

    • **易于PHP/Symfony开发者接受** –
      客户的IT团队包括PHP开发者。引入新技术(比如Node.js)就意味着需要雇佣新的能够更好的维护系统的开发者。

    • 清晰的项目结构 –
      Symfony2并没有利用非常复杂的项目结构,但它缺省的项目结构非常清晰。招聘新的开发者进入工程是非常简单的,因为Symfony2的代码对他们来讲非常熟悉。

    • 现成的组件 – 遵循DRY理念…
      没有人想去重新构造,所以我们也不想。我们广泛使用Symfony2的控制组件,该组件对于生成CLI命令、制作应用(调试工具栏)性能分析工具以及记录器等是一个非常棒的框架。

    在使用之前,我们做了性能测试以确保其能够处理设定好的任务量。我们开发了概念验证模型并使用它运行JMeter。结果令人印象深刻-700req/s的响应时间最高50ms。这是我们确信,在我们的这个项目中可以使用这一复杂结构。

  • 应用分析与监控

    我们使用了Symfony2的工具来监控我们的应用。Symfony2有一个非常棒的性能分析组件,可以用来收集特定方法的执行时间,尤其是那些与第三方服务有关的方法。这样我们就可以找出潜在的弱点以及应用中最耗时的部分。

    详细的日志是必须的。为此,我们使用PHP的Monolog库,它允许我们生成友好的、完全能够被开发者和系统管理者理解的格式化日志记录。必须时常谨记的是日志中要尽可能的增加细节,我们发现日志越详细越好。我们使用了不同的日志级别:

    • 调试 – 一些将要产生的信息 –
      比如在调用外部网络服务之前的请求信息;一些已经发生的信息-从API请求返回的响应;

    • 错误 –
      出现了错误但是请求流还没有停止(比如从第三方API返回的错误响应);

    • 危险 – 哎呦… 应用崩溃了。

    在产品环境下,你能够看到Error级别日志,以及它下面的Critical级别日志。在开发/测试环境中,还有Debug日志可以看到。

    我们将日志分成不同的文档(在Monolog库中他们被称为“通道”)。主日志文件用于存储所有应用范围的错误信息以及特定通道中的短日志信息。我们将来自不同通道中的详细日志信息保存在不同的文件中。

  • 可扩展性

    扩展平台上的应用层级并不是件难事。
    HAProxy的性能并不会被常时间的消耗,我们只需要考虑避免单点故障(SPoF)
    所需的冗余。

    在此模式下只需要增加其他应用节点即可。

    数据层

    我们使用Redis和MySQL存储所有的数据。当Redis做为主数据存储时,MySQL则用于第三层的缓存存储。

  • Redis

    当设计我们的系统时,我们需要考虑选择一个能够满足我们设定要求的数据库:

    • 存储大量数据时(约2.5亿记录)不能降低性能

    • 主要使用基于特定资源标识符的简单GETs(没有查找或复杂的SELECTs)

    • 能够在单个请求中获取大量的资源以最小化延迟

    经过一些调查,我们决定使用Redis。

    • 我们进行的所有操作的复杂度为 O(1) 或
      O(N),N代表我们检索的主键数目。这意味着主键空间的大小不会影响到性能。

    • 一次检索的主键数目大于100时我们大多使用MGET命令,与在一次回路中使用多个GETs相比,那样可以忽略网络延迟。

    最近我们在主从复制模式下运行了两台Redis服务器。每个的配置为: Xeon
    E5-2650v2@2.60GHz, 128GB, SSD. 内存限制在100GB…内存经常被占满 🙂

    图片 15

  • 由于应用并没有完全耗尽单一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曲线实现”失去主键“比的可视化。

    图片 16

    一年之后,我可以说我们已经完全融入了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上你也能运行的很慢。选择一个能够提供良好开发环境的技术,而不是去对着不友好的工具进行抱怨(降低开发的士气)。

 

图片 17

图片 17

CentOS 6.3安装Redis
http://www.linuxidc.com/Linux/2012-12/75314.htm

谁是背后的应用程序

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

方案三:

方案三:

Redis安装部署学习笔记
http://www.linuxidc.com/Linux/2014-07/104306.htm

相关文章

  • 使用Symfony2在一周内处理一亿个请求 –
    我们的整个应用程序的概述

  • 推到极致 –
    Symfony2满足高性能需求 –
    Symfony2软件架构的细节特点描述

程序写MySQL, 解析binlog,数据放入队列写Redis
读Redis
参考
《利用Canal完成Mysql数据同步Redis》

程序写MySQL, 解析binlog,数据放入队列写Redis
读Redis
参考 《利用Canal完成Mysql数据同步Redis》

Redis配置文件redis.conf 详解
http://www.linuxidc.com/Linux/2013-11/92524.htm

图片 19

图片 19

Redis
的详细介绍
:请点这里
Redis
的下载地址
:请点这里

方案四:

方案四:

数据:

服务器:

  • 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 (第三层缓存)

程序写Redis,并将写放入MQ写MySQL
读Redis

程序写Redis,并将写放入MQ写MySQL
读Redis

平台:

图片 21

图片 21

图片 23

监控:

  • Icinga

  • Collectd

应用程序:

  • HAProxy with Keepalived

  • Varnish

  • PHP (PHP-FPM) with Symfony2 Framework

数据存储:

  • MySQL (master-master) with HAProxy load balancing

  • Redis (master-slave)

背景

差不多一年前,我们的朋友带着一个难以解决的问题来到我们的办公室。他们正在运行一个快速增长的电子商务新兴公司,当时他们希望将其扩展到国际水平。

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

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

图片 24 图片 25 

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

进一步维护这样的应用可能是一个噩梦。由于部分代码已经被复制,更改一个网站,可能会导致业务逻辑的不一致

  • 他们总是需要在所有的web应用程序中进行相同的更改。

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

根据这一观察,我们的第一步是提取核心的关键业务功能到一个单独的服务中(这是本文的范围)。它是面向服务的架构模式。在整个系统范围内考虑“关注点分离”的原则。该服务是保持一种逻辑的,具体的更高级别的业务功能。给你一个真实的例子

  • 服务可以是一个搜索引擎,销售系统等。

前端网站通过一个REST
API
来和服务进行通信。响应是基于JSON格式的。我们选择它的原因是简单性,相反SOAP始终对开发者来说比较困难(没有人喜欢分析XMLS…;-))

提取的服务并不处理如身份验证和会话管理之类的东西。这是必须的,这些事情是在一个更高的层次来处理的。前端网站负责这一点,因为只有他们才能确定他们的用户。这样,我们将服务更简化

在进一步扩展的问题和代码的东西上。没有什么不好的,因为它有不同的任务来处理。

1

优点:


不同的子系统(服务)可以很容易被完全不同的开发团队开发。开发者之间可以互不干涉。

– 不用处理用户授权和访问问题,因此就不存在常见的等级问题了。

– 在一个地方维护业务逻辑-不同的前端网站之间不存在冗余的功能。

– 易于该服务被大众所接受

缺点:


系统管理者的工作量更大- 因为服务是基于其自身的架构体系,所以系统管理员就需要对该架构增加关注。

– 保持向后兼容性-在一年的维护中,API
方法的改变多的会不计其数。 问题是这些改变千万不能破坏向后兼容性,不然每个前端网站的代码都需要修改,而且同时部署所有网站时会增加程序员工作…一年之后,所有的方法仍然能够与第一版的文档兼容。

应用层

图片 26

根据请求流,第一层是应用层,应用层里面包括HAProxy负载均衡器,Varnish和Symfony2
网络应用。来自前端网站的请求首先到达HAProxy,然后通过HAProxy分发到应用节点中。

应用节点配置

  • Xeon E5-1620@3.60GHz, 64GB RAM, SATA

  • Varnish

  • Apache2

  • PHP 5.4.X running as PHP-FPM, with APC bytecode cache

我们已经拥有三个这样的应用服务器。它是双活模式下的N+1模式 –
”备份“服务器主动处理请求。

保持Varnish在每个节点中的独立性使得快取命中率更低,但是这种方式下我们就不存在SPOF问题(一个节点失效,全部系统停止运转)。我们这样做的目的是考虑可用性高于性能(在我们的案例中性能不是问题)。

我们选择Apache2,它也被用在前端网站服务器中。避免混合进许多技术使得系统管理员的维护更加容易。

Symfony2 应用

应用本身是建立在Symfony2的顶层之上。它是一个完全PHP的栈框架,提供丰富的有用组件,这些组件能够加速开发的进程。将典型的REST服务建立在一个复杂的框架之上可能对某些人来说不可思议,让我对其中的原因进行说明:

  • **易于PHP/Symfony开发者接受** –
    客户的IT团队包括PHP开发者。引入新技术(比如Node.js)就意味着需要雇佣新的能够更好的维护系统的开发者。

  • 清晰的项目结构 –
    Symfony2并没有利用非常复杂的项目结构,但它缺省的项目结构非常清晰。招聘新的开发者进入工程是非常简单的,因为Symfony2的代码对他们来讲非常熟悉。

  • 现成的组件 – 遵循DRY理念…
    没有人想去重新构造,所以我们也不想。我们广泛使用Symfony2的控制组件,该组件对于生成CLI命令、制作应用(调试工具栏)性能分析工具以及记录器等是一个非常棒的框架。

在使用之前,我们做了性能测试以确保其能够处理设定好的任务量。我们开发了概念验证模型并使用它运行JMeter。结果令人印象深刻-700req/s的响应时间最高50ms。这是我们确信,在我们的这个项目中可以使用这一复杂结构。

应用分析与监控

我们使用了Symfony2的工具来监控我们的应用。Symfony2有一个非常棒的性能分析组件,可以用来收集特定方法的执行时间,尤其是那些与第三方服务有关的方法。这样我们就可以找出潜在的弱点以及应用中最耗时的部分。

详细的日志是必须的。为此,我们使用PHP的Monolog库,它允许我们生成友好的、完全能够被开发者和系统管理者理解的格式化日志记录。必须时常谨记的是日志中要尽可能的增加细节,我们发现日志越详细越好。我们使用了不同的日志级别:

  • 调试 – 一些将要产生的信息 –
    比如在调用外部网络服务之前的请求信息;一些已经发生的信息-从API请求返回的响应;

  • 错误 –
    出现了错误但是请求流还没有停止(比如从第三方API返回的错误响应);

  • 危险 – 哎呦… 应用崩溃了。

在产品环境下,你能够看到Error级别日志,以及它下面的Critical级别日志。在开发/测试环境中,还有Debug日志可以看到。

我们将日志分成不同的文档(在Monolog库中他们被称为“通道”)。主日志文件用于存储所有应用范围的错误信息以及特定通道中的短日志信息。我们将来自不同通道中的详细日志信息保存在不同的文件中。

可扩展性

扩展平台上的应用层级并不是件难事。
HAProxy的性能并不会被常时间的消耗,我们只需要考虑避免单点故障(SPoF)
所需的冗余。

在此模式下只需要增加其他应用节点即可。

数据层

我们使用Redis和MySQL存储所有的数据。当Redis做为主数据存储时,MySQL则用于第三层的缓存存储。

Redis

当设计我们的系统时,我们需要考虑选择一个能够满足我们设定要求的数据库:

  • 存储大量数据时(约2.5亿记录)不能降低性能

  • 主要使用基于特定资源标识符的简单GETs(没有查找或复杂的SELECTs)

  • 能够在单个请求中获取大量的资源以最小化延迟

经过一些调查,我们决定使用Redis。

  • 我们进行的所有操作的复杂度为 O(1) 或
    O(N),N代表我们检索的主键数目。这意味着主键空间的大小不会影响到性能。

  • 一次检索的主键数目大于100时我们大多使用MGET命令,与在一次回路中使用多个GETs相比,那样可以忽略网络延迟。

最近我们在主从复制模式下运行了两台Redis服务器。每个的配置为: Xeon
E5-2650v2@2.60GHz, 128GB, SSD. 内存限制在100GB…内存经常被占满 🙂

图片 27

更多详情见请继续阅读下一页的精彩内容
http://www.linuxidc.com/Linux/2014-11/109455p2.htm

图片 28

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图