画布 1
PHP知识体系
  Linux服务器
    OS基础概念
      内存
      进程
        进程之间通信的方式
          共享内存 Shared Memory
          管道 PIPE
          消息队列 MQ
          信号量 Signal
          套接字 Socket
        线程之间通信的方式
          互斥锁
          条件变量
          读写锁
          线程信号
        进程与线程
          进程是分配资源的基本单位，线程是执行的基本单位
          早期计算机没有操作系统，效率极低；
批处理操作系统出现，但是缺点是只能有一个任务；
进程出现，一个进程就是一个任务，进程间的资源是独立单元，缺点是进程内只能进行串行处理；
线程出现，能协调进程内的子任务共享进程内的资源，并行工作。
          进程是资源分配的最小单元，与其他进程资源互相独立；线程是任务调度的最小单元，共用进程内的资源
      I/O
      文件系统
      锁
        死锁
          死锁指的是由于两个或多个执行单元之间相互等待对方结束而引起阻塞的情况
          一个线程T1获得了对资源R1的访问权。一个线程T2获得了对资源R2的访问权。
T1请求对R2的访问权但是由于此权力被T2所占而不得不等待。
T2请求对R1的访问权但是由于此权力被T1所占而不得不等待。
T1和T2将永远维持等待状态，此时我们陷入了死锁的处境
        乐观锁与悲观锁
          乐观锁
            每次去拿数据的时候都认为别人不会修改，所以不会上锁，但是在更新的时候会判断一下在此期间别人有没有去更新这个数据，可以使用版本号等机制。乐观锁适用于多读的应用类型，这样可以提高吞吐量，像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
          悲观锁
            每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁，这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制，比如行锁，表锁等，读锁，写锁等，都是在做操作之前先上锁。
    常用命令
      文件相关
        ls
        tar
        ……
      进程相关
        ps
        top
        ……
      文本操作相关
        sed
        awk
        sort
        ……
    C10K问题
      什么是C10K问题
        C10K问题全称是concurrent 10000 connection。是指服务器同时支持成千上万个客户端的问题。
      为什么会有C10K问题
        最初的服务器都是基于进程/线程模型的，新到来一个TCP连接，就需要分配1个进程（或者线程）。
而进程又是操作系统最昂贵的资源，一台机器无法创建很多进程。
如果是C10K就要创建1万个进程，那么操作系统是无法承受的。
如果是采用分布式系统，维持1亿用户在线需要10万台服务器，成本巨大，
也只有Facebook，Google，雅虎才有财力购买如此多的服务器。这就是C10K问题的本质。
      解决方案
        每个进程/线程处理一个连接
          这一思路最为直接。但是由于申请进程/线程会占用相当可观的系统资源，
同时对于多进程/线程的管理会对系统造成压力，因此这种方案不具备良好的可扩展性。
          资源占用过多，可扩展性差
        每个进程/线程处理多个连接（IO多路复用）
          传统思路
            直接循环处理多个连接
            任一文件句柄的不成功会阻塞住整个应用
          select
            有连接请求抵达了再检查处理
            句柄上限+重复初始化+逐个排查所有文件句柄状态效率不高
          poll
            设计新的数据结构提供使用效率
            逐个排查所有文件句柄状态效率不高
          epoll
            只返回状态变化的文件句柄
            依赖特定平台（Linux）
    CGI和FastCGI
      CGI
        CGI是为了保证web server传递过来的数据是标准格式的，它是一个协议，方便CGI程序的编写者。
        CGI针对每个http请求都是fork一个新进程来进行处理，处理过程包括解析php.ini文件，初始化执行环境等，然后这个进程会把处理完的数据返回给web服务器，最后web服务器把内容发送给用户，刚才fork的进程也随之退出。 如果下次用户还请求动态资源，那么web服务器又再次fork一个新进程，周而复始的进行。
      FastCGI
        Fastcgi是CGI的更高级的一种方式，是用来提高CGI程序性能的。
        而Fastcgi则会先fork一个master，解析配置文件，初始化执行环境，然后再fork多个worker。当请求过来时，master会传递给一个worker，然后立即可以接受下一个请求。这样就避免了重复的劳动，效率自然是高。而且当worker不够用时，master可以根据配置预先启动几个worker等着；当然空闲worker太多时，也会停掉一些，这样就提高了性能，也节约了资源。这就是Fastcgi的对进程的管理。大多数Fastcgi实现都会维护一个进程池。
      PHP-FPM
        PHP FastCGI Process Manager
        它是一个实现了Fastcgi协议的程序,用来管理Fastcgi起的进程的,即能够调度php-cgi进程的程序。现已在PHP内核中就集成了PHP-FPM，使用--enalbe-fpm这个编译参数即可。另外，修改了php.ini配置文件后，没办法平滑重启，需要重启php-fpm才可。此时新fork的worker会用新的配置，已经存在的worker继续处理完手上的活。
  MySQL数据库
    ACID
      四项约束
        Atomicity 原子性
          一个事务中的所有操作，要么全部完成，要么全部不完成
        Consistency 一致性
          事务开始之前和事务结束之后，数据库的完整性没有被破坏
        Isolation 隔离性
          防止多个事务并发执行时由于交叉执行而导致的数据不一致
            事务隔离四个级别
              Read Uncommitted 读未提交
              Read Committed 读提交
              Repeatable Read 可重复读
              Serializable 串行化
        Durability 持久性
          事务处理结束后，对数据的修改是永久的，即便系统故障也不会丢失
    索引
      索引类型
        主键索引
          主键
        唯一索引
          类似主键索引，全表内唯一
        普通索引
        联合索引
          多个列联合组成的索引，符合左值优先原则
        全文索引
      索引优化
        EXPLAIN语句显示索引使用情况
          id
            SELECT识别符，这是SELECT的查询序列号
          select_type
          table
            输出的行所用的表
          type
            连接类型
          possible_keys
            指出MySQL能使用哪个索引在该表中找到行
          key
            显示MySQL实际决定使用的键(索引)。如果没有选择索引，键是NULL。
          key_len
            显示MySQL决定使用的键长度。如果键是NULL，则长度为NULL。
          ref
            显示使用哪个列或常数与key一起从表中选择行。
          rows
            显示MySQL认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数。
          extra
            关于MYSQL如何解析查询的额外信息
        索引限制情况
          使用不等号，无法索引
          使用函数，无法索引
          使用LIKE，第一个字符不能是通配符，否则无法索引
          JOIN语句中条件字段类型不一样，不会使用索引
    SQL语句优化
      子查询语句用JOIN语句代替
      JOIN语句拆分成多次查询
      不使用视图View
    主从同步
      同步流程
        1. Slave 上面的 IO 线程连接上 Master，并请求从指定日志文件的指定位置（或者从最开始的日志）之后的日志内容
        2. Master 接收到来自 Slave 的 IO 线程的请求后，通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外，还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置
        3. Slave 的 IO 线程接收到信息后，将接收到的日志内容依次写入到 Slave 端的 Relay Log 文件（mysql-relay-bin.xxxxxx）的最末端，并将读取到的 Master 端的 bin-log 的文件名和位置记录到 master-info 文件中，以便在下一次读取的时候能够清楚地告诉 Master “我需要从某个 bin-log 的哪个位置开始往后的日志内容,请发给我”
        4. Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后，会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句，并在自身执行这些 Query。这样，实际上就是在 Master 端和 Slave 端执行了同样的 Query，所以两端的数据是完全一样的
      常用架构
        一主多从 Master Slaves
        互为主从 Dual Masters
          适用于临时性、可丢失、可覆盖的数据场景
        级联复制架构 Master Slaves Slaves
        Dual Masters与级联复制结合 Master Master Slaves
    分表
      水平切分
      垂直切分
    分库
      全局主键生成策略
    常用中间件
      King Shard
      阿里云DRDS
      MySQL Proxy
  NoSQL存储
    Redis
      单线程模型
        RDB
          以快照的形式将数据持久化到磁盘
            当redis需要做持久化时，redis会fork一个子进程，子进程将数据写到磁盘上一个临时RDB文件中；
当子进程完成写临时文件后，将原来的RDB替换掉，这样的好处就是可以copy-on-write
        AOF
          追加写入AOF文件
            默认情况下每执行一条命令就写入一次AOF文件
折中方案是配置appendfsync everysec 每秒写入一次
      Key限制512MB，Value限制512MB
      数据结构
        string 字符串
        set 集合
        sorted set 有序集合
        list 列表
        hash 哈希散列
        bitmap 位图
      主从同步
        原理
          全量同步
            Slave发送SYNC命令
Master执行BGSAVE，发送快照文件
Slave收到快照文件，载入数据
Master继续发送写命令，Slave载入数据完成后，接收命令
          增量同步
            Master每执行一次写命令，Slave就接收同步执行
          首次同步先进行全量同步，之后都是增量同步
永远优先尝试增量同步，不成功再进行全量同步
        架构
          树形主从
          链式主从
      集群方案
        官方方案 3.0之后提供
          Redis Cluster
            采用固定分片
CRC16后对16384取模
            一主多从结构，Master挂掉，Slave选举
        Redis Sharding
          采用一致性HASH
        中间件
          twemproxy
          codis
      优势与限制
        Redis能做什么
          缓存
          排行榜 list/zset
          计数器/限速器（统计播放数据/浏览量/在线人数等）
          好友关系（点赞/共同好友关系）
          简单的消息队列（订阅发布/阻塞队列）
          Session服务器
        Redis不能做什么
          数据量太大不合适
          数据访问频率太低不合适
  网络与架构
    负载均衡
      分类
        DNS负载均衡
          DNS解析返回最近服务器地址
          优点
            简单、成本低，就近访问，提升访问速度
          缺点
            DNS更新不及时，扩展性差，分配策略简单
        硬件负载均衡
          主要设备
            A10
            F5
            NetScaler
          优点
            可以支持百万QPS以上，功能强大、性能强大、稳定性高、支持安全防护
          缺点
            价格昂贵、扩展能力差
        软件负载均衡
          HAProxy 7层
          LVS 4层
            也就是主要通过报文中的目标地址和端口
再加上负载均衡设备设置的服务器选择方式
决定最终选择的内部服务器
          Nginx 7层
            也称为“内容交换”，也就是主要通过报文中的真正有意义的应用层内容
再加上负载均衡设备设置的服务器选择方式，决定最终选择的内部服务器。
          优点
            简单、便宜、灵活
          缺点
            性能一般，功能有限，不具备防火墙防DDOS功能
      算法
        任务平分类
          轮询
            负载均衡系统收到请求后，按照顺序轮流分配到服务器上
          加权轮询
            根据服务器权重进行任务分配
        负载均衡类
          负载最低优先
            站在服务器的角度来进行分配
        性能最优类
          性能最优先
            站在客户端的角度来进行分配
        HASH类
          源地址HASH
            将同一个源IP地址的任务分配给同一个服务器进行处理
          ID HASH
            将某个ID标识的业务分配到同一个服务器进行处理
      DDOS
        即黑客控制众多源客户端，使用虚假IP地址对同一目标发送SYN攻击
通常这种攻击会大量发送SYN报文，耗尽服务器上的相关资源，以达到Denial of Service(DoS)的目的
        四层模式下这些SYN攻击都会被转发到后端的服务器上
而七层模式下这些SYN攻击自然在负载均衡设备上就截止，不会影响后台服务器的正常运营
      KeepAlived
        主要用作Real Server的健康状态检查以及Load Balance主机和Back Up主机之间failover的实现
        高可用web架构: LVS+keepalived+nginx+apache+php+eaccelerator
    HTTP状态码
      20X
        200 OK
          请求已成功，请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。
        202 Accepted
          服务器已接受请求，但尚未处理。正如它可能被拒绝一样，最终该请求可能会也可能不会被执行。
在异步操作的场合下，没有比发送这个状态码更方便的做法了。
      30X
        301 Moved Permanently
          被请求的资源已永久移动到新位置，并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
        302 Move temporarily
          请求的资源临时从不同的 URI响应请求。由于这样的重定向是临时的，
客户端应当继续向原有地址发送以后的请求。
只有在Cache-Control或Expires中进行了指定的情况下，这个响应才是可缓存的。
        304 Not Modified
          如果客户端发送了一个带条件的 GET 请求且该请求已被允许，
而文档的内容（自上次访问以来或者根据请求的条件）并没有改变，则服务器应当返回这个状态码。
304响应禁止包含消息体，因此始终以消息头后的第一个空行结尾。
      40X
        400 Bad Request
          语义有误，当前请求无法被服务器理解。除非进行修改，否则客户端不应该重复提交这个请求。
        404 Not Found
          请求失败，请求所希望得到的资源未被在服务器上发现。
      50X
        500 Internal Server Error
          服务器遇到了一个未曾预料的状况，导致了它无法完成对请求的处理。
一般来说，这个问题都会在服务器端的源代码出现错误时出现。
        502 Bad Gateway
          作为网关或者代理工作的服务器尝试执行请求时，从上游服务器接收到无效的响应。
        503 Service Unavailable
          由于临时的服务器维护或者过载，服务器当前无法处理请求。这个状况是临时的，并且将在一段时间以后恢复。如果能够预计延迟时间，那么响应中可以包含一个 Retry-After 头用以标明这个延迟时间。
        504 Gateway Timeout
          作为网关或者代理工作的服务器尝试执行请求时，未能及时从上游服务器（URI标识出的服务器，例如HTTP、FTP、LDAP）或者辅助服务器（例如DNS）收到响应。
    代理
      正向代理
        正向代理是一个位于客户端和目标服务器之间的代理服务器
为了从原始服务器取得内容，客户端向代理服务器发送一个请求，并且指定目标服务器
之后代理向目标服务器转交并且将获得的内容返回给客户端
      反向代理
        对于客户端来说，反向代理就好像目标服务器。并且客户端不需要进行任何设置
客户端向反向代理发送请求，接着反向代理判断请求走向何处，并将请求转交给客户端
使得这些内容就好似他自己一样，一次客户端并不会感知到反向代理后面的服务
也因此不需要客户端做任何设置，只需要把反向代理服务器当成真正的服务器就好了
    消息队列
      NSQ
        组成
          nsqd
            接收、队列和传送消息到客户端的守护进程
          nsqlookupd
            管理的拓扑信息，并提供了最终一致发现服务的守护进程
          nsqadmin
            一个 Web UI 来实时监控集群和执行各种管理任务
  PHP语言
    PHP内核
      写时复制
        当用一个变量去给另外一个变量赋值之后，实际上这两个变量一开始会指向同一块内存。在这个例子中，$a 和 $b 在第二步结束之后，就会指向内存中保存了数组信息的那一块数据。而在第三步修改 $b 的数据时，首先会开辟出一块新的内存把原有的数据拷贝过去，并将 $b 指向这块内存，然后再修改数据。
      数据结构
        变量（结构体）
          struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
        类型（联合）
          typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
    抽象类与接口
      区别
        两者表达的概念不一样。抽象类是一类事物的高度聚合
那么对于继承抽象类的子类来说，对于抽象类来说，属于“是”的关系；
而接口是定义行为规范，因此对于实现接口的子类来说
相对于接口来说，是“行为需要按照接口来完成”
          “狗”是抽象类，拉布拉多、黑背、哈士奇是“狗”的继承类
          狗可以叫，鸟也可以叫，“叫”这个动作就是接口
        抽象类在定义类型方法的时候，可以给出方法的实现部分，也可以不给出
而对于接口来说，其中所定义的方法都不能给出实现部分
        继承类对于两者所涉及方法的实现是不同的，继承类对于抽象类所定义的抽象方法，可以不用重写
也就是说，可以延用抽象类的方法，而对于接口类所定义的方法或者属性来说
在继承类中必须要给出相应的方法和属性实现
        在抽象类中，新增一个方法的话，继承类中可以不用作任何处理
而对于接口来说，则需要修改继承类，提供新定义的方法
      接口的应用场合
        类与类之间需要特定的接口进行协调，而不在乎其如何实现
        作为能够实现特定功能的标识存在，也可以是什么接口方法都没有的纯粹标识
        需要将一组类视为单一的类，而调用者只通过接口来与这组类发生联系
        需要实现特定的多项功能，而这些功能之间可能完全没有任何联系
      抽象类的应用场合
        定义了一组接口，但又不想强迫每个实现类都必须实现所有的接口
可以用 abstract class 定义一组方法体，甚至可以是空方法体，然后由子类选择自己所感兴趣的方法来覆盖
        某些场合下，只靠纯粹的接口不能满足类与类之间的协调
还必需类中表示状态的变量来区别不同的关系
abstract 的中介作用可以很好地满足这一点
        规范了一组相互协调的方法，其中一些方法是共同的，与状态无关的，可以共享的，无需子类分别实现
而另一些方法却需要各个子类根据自己特定的状态来实现特定的功能
    设计模式
      工厂模式
Factory
        简单工厂模式
Simple Factory
          简单工厂模式的工厂类一般是使用静态方法
通过接收的参数的不同来返回不同的对象实例
不修改代码的话，是无法扩展的
            用来生产同一等级结构中的任意产品
对于增加新的产品，无能为力
        工厂方法模式
Factory Method
          工厂方法是针对每一种产品提供一个工厂类
通过不同的工厂实例来创建不同的产品实例
在同一等级结构中，支持增加任意产品
            用来生产同一等级结构中的固定产品
支持增加任意产品
        抽象工厂模式
Abstract Factory
          抽象工厂是应对产品族概念的。
比如说，每个汽车公司可能要同时生产轿车，货车，客车
那么每一个工厂都要有创建轿车，货车和客车的方法。
应对产品族概念而生，增加新的产品线很容易，但是无法增加新的产品。
            用来生产不同产品族的全部产品
对于增加新的产品，无能为力
支持增加产品族
      单例模式
Singleton
        应用场合
          应用程序与数据库交互
            一个应用中会存在大量的数据库操作，比如过数据库句柄来连接数据库这一行为
使用单例模式可以避免大量的new操作，因为每一次new操作都会消耗内存资源和系统资源
          控制配置信息
            如果系统中需要有一个类来全局控制某些配置信息， 那么使用单例模式可以很方便的实现
        特点
          私有的构造方法 (防止类外实例化)
          私有的克隆方法 (防止通过克隆生成对象)
          私有的静态属性 (保存类的实例)
          公有的静态方法 (调取这个类相当一个接口 )
      观察者模式
Observer
        避免组件之间紧密耦合
        观察者模式是一种事件系统，意味着这一模式允许某个类观察另一个类的状态
当被观察的类状态发生改变的时候，观察类可以收到通知并且做出相应的动作
        当新对象要填入的时候，只需要在主题（又叫可观察者）中进行注册
注册方式很多，你可以在构造的时候，或者框架访问的接口中进行注册
然后实现代码直接在新对象的接口中进行
这降低了主题对象和观察者对象的耦合度
        应用于框架内事件机制的开发
在别的地方编写代码注册事件之后
在一个地方进行事件的广播
从而调用所有的观察者方法
      前端控制器模式
FrontendController
        统一入口
        路由分发
      装饰器模式
        不修改原类代码和继承的情况下动态扩展类的功能
例如框架的每个Controller文件会提供before和after方法
在某个方法或输出之前执行或者之后执行，用于修饰
      迭代器模式
        提供一个方法顺序访问一个聚合对象中各个元素，在PHP将继承Iterator类 - yield
      工厂模式中，重要的是工厂类，而不是产品类。
产品类可以是多种形式，多层继承或者是单个类都是可以的。
但要明确的，工厂模式的接口只会返回一种类型的实例，
这是在设计产品类的时候需要注意的，最好是有父类或者共同实现的接口。
使用工厂模式，返回的实例一定是工厂创建的，而不是从其他对象中获取的。
工厂模式返回的实例可以不是新创建的，返回由工厂创建好的实例也是可以的。
  缓存
    Memcache
      多线程模型
        采用libevent和epoll
      只支持保存字符串
        Key限制250个字符，Value限制1MB大小，默认最大超时时间30天
      缓存淘汰算法
        LRU Least Recently Used 最近使用置换算法
          链表和HashMap实现
            当需要插入新的数据项的时候，如果新数据项在链表中存在（一般称为命中）
则把该节点移到链表头部，如果不存在，则新建一个节点，放到链表头部
若缓存满了，则把链表最后一个节点删除即可
在访问数据的时候，如果数据项在链表中存在，则把该节点移到链表头部
否则返回-1。这样一来在链表尾部的节点就是最近最久未访问的数据项
        FIFO First In First Out 先进先出算法
          链表实现
            利用一个双向链表保存数据，当来了新的数据之后便添加到链表末尾
如果Cache存满数据，则把链表头部数据删除，然后把新的数据添加到链表末尾
在访问数据的时候，如果在Cache中存在该数据的话，则返回对应的value值
否则返回-1。如果想提高访问效率，可以利用hashmap来保存每个key在链表中对应的位置
        LFU Least Frequently Used 最少使用置换算法
          数组和HashMap实现
            利用一个数组存储 数据项，用hashmap存储每个数据项在数组中对应的位置
然后为每个数据项设计一个访问频次，当数据项被命中时，访问频次自增
在淘汰的时候淘汰访问频次最少的数据
这样一来的话，在插入数据和访问数据的时候都能达到O(1)的时间复杂度
在淘汰数据的时候，通过选择算法得到应该淘汰的数据项在数组中的索引
并将该索引位置的内容替换为新来的数据内容
即可这样的话，淘汰数据的操作时间复杂度为O(n)
      集群算法
        一致性哈希
          首先求出memcached服务器（节点）的哈希值，并将其配置到0～2^32的圆（continuum）上
然后采用同样的方法求出存储数据的键的哈希值，并映射到相同的圆上
然后从数据映射到的位置开始顺时针查找，将数据保存到找到的第一个服务器上
如果超过2^32仍然找不到服务器，就会保存到第一台memcached服务器上
        改进型一致性哈希
          引入虚拟节点的概念，用以解决在节点间分布不均匀的问题。
      缓存雪崩与缓存穿透处理方式
        独立的更新进程
          这种方法适合不需要即时运算的全局数据。
但对用户对象、朋友列表、评论之类的就不太适用。
        使用锁
          A 请求的缓存没命中
A 请求“锁住”缓存 key
B 请求的缓存没命中
B 请求需要等待直到“锁”释放
A 请求完成，并且释放“锁”
B 请求缓存命中（由于 A 的运算）
      内存分配
        Slab Allocator
          slab是特定大小的chunk的组，并根据增长因子(factor)，划分成不同slab class
分配内存时，每次分配一个page(默认1MB)给某个slab
并根据slab的大小，切分成多个chunk数据存储在chunk中
Memcached根据收到的数据的大小，选择最适合数据大小的slab
          chunk浪费: 缓存数据没有填充满chunk
page浪费: 一个page的容量不能被slab的大小整除。
slab浪费: 某个slab的内存没有完全被利用，只存储了少量数据，却占用一个page
          按照预先规定的大小，将分配的内存分割成特定长度的块，以此来解决内存碎片问题
  方法论
    CAP理论
      Consistence 一致性
        所有节点在同一时刻都能看到相同的数据
        对某个特定的客户端来说，读操作保证能够返回最新的写操作结果
      Availability 可用性
        每个请求都能得到成功或者失败的响应
        非故障的节点在合理的时间内返回合理的响应（不是错误和超时的响应）
      Partition Tolerance 分区容错性
        出现消息丢失或者分区错误时系统能够继续运行
        当出现网络分区后，系统能够继续履行职责
      因为网络无法做到100%可靠，所以必须选择P，因此只能有CA、CP架构
        CP架构
          Consistency/Partition Tolerance
        CA架构
          Consistency/Availability
    BASE理论
      Basically Available 基本可用
        分布式系统在出现故障时，允许损失部分可用性，保证核心可用
      Soft State 软状态
        允许系统存在中间状态，而该中间状态不会影响系统整体可用性
      Eventual Consistency 最终一致性
        系统中所有的数据副本经过一定时间之后，最终能够达到一致的状态
      即使无法做到强一致性，但应用可以采用适合的方法达到最终一致性
    FEMA方法
      概念
        Failure Mode and Effects Analysis 故障模式与影响分析
        失效模式与后果分析、失效模式与效应分析、故障模式与后果分析
      具体分析方法
        给出初始的架构设计图
        假设架构中某个部件发生故障
        分析此故障对系统功能造成的影响
        根据分析结果，判断架构是否需要进行优化
      包含部分
        功能点
          从用户角度看到的功能点
        故障模式
          系统会出现什么样的故障，包括故障点和故障形式
        故障影响
          当发生故障模式中描述的故障时，功能点具体会受到什么影响
        严重程度
          站在业务角度故障的影响程度，分“致命/高/中/低/无”五个档次
        故障原因
          不同故障原因发生概率不同、不同故障原因检测手段不一样、不同故障原因处理措施不一样
        故障概率
          某个故障原因发生的概率，分“高/中/低”三档
        风险程度
          综合严重程度和故障概率来一起判断某个故障的最终等级
        已有措施
          针对具体的故障原因，系统现在是否提供了某些措施来应对，包括：检测告警、容错、自恢复等
        规避措施
          为了降低故障发生概率而做的一些事情，可以是技术手段，可以是管理手段
        解决措施
          为了解决问题而做的一些事情，一般都是技术手段
        后续规划
          针对这些不足的地方，再结合风险程度进行排序，给出后续的改进计划
  常用工具
    持续集成 CI
      Jenkins
      Git/GitLab
    监控
      Grafana
      Prometheus
  常见实用场景
    秒杀系统架构设计
    环形队列实现秒级Cronjob
http://img4.07net01.com/upload/images/2016/05/17/178687170837311.png
http://www.cnblogs.com/mydomain/archive/2010/09/23/1833369.html
https://www.cnblogs.com/LUO77/p/5816326.html
http://blog.163.com/jimking_2010/blog/static/1716015352013102510748824/
https://www.zhihu.com/question/21419897
https://kb.cnblogs.com/page/188170/
https://nsq.io/
https://github.com/nsqio/nsq
https://zhuanlan.zhihu.com/p/37081073
http://www.infoq.com/cn/news/2015/02/nsq-distributed-message-platform
http://www.php-internals.com/book/
http://www.cnblogs.com/dolphin0520/p/3749259.html
http://www.innomysql.com/%E9%AB%98%E5%B9%B6%E5%8F%91%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%B8%8E%E4%BC%98%E5%8C%96/
https://yq.aliyun.com/articles/38090
https://blog.csdn.net/w302974215/article/details/49813969
https://www.cnblogs.com/wangzhongqiu/p/6557596.html
http://www.cnblogs.com/hohoa/p/7739271.html
https://blog.csdn.net/ligang2585116/article/details/72859359
https://mp.weixin.qq.com/s/eDMV25YqCPYjxQG-dvqSqQ