<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Zeyu Lee</title>
        <description>ZeyuLee 的小站</description>        
        <link>http://zeyulee.com</link>
        <atom:link href="http://zeyulee.com/feed.xml" rel="self" type="application/rss+xml" />
        
            <item>
                <title>Azkaban 3插件的安装与配置</title>
                <description>&lt;p&gt;Azkaban的插件分为2类，一种是web-server用的报表、展示类插件（viwer），一种是exec-server用的工作流类型插件。&lt;/p&gt;

&lt;h1 id=&quot;编译&quot;&gt;编译&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/azkaban/azkaban-plugins.git

&lt;span class=&quot;c&quot;&gt;# 全部编译&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;azkaban-plugins
ant
cp ./dist/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/packages/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz /plugins/path

&lt;span class=&quot;c&quot;&gt;# 单独编译&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;azkaban-plugins/jobtype
ant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;安装&quot;&gt;安装&lt;/h1&gt;

&lt;h2 id=&quot;web-server-插件&quot;&gt;web-server 插件&lt;/h2&gt;

&lt;p&gt;目前有以下几个：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;hdfsviewer&lt;/li&gt;
  &lt;li&gt;javaviewer&lt;/li&gt;
  &lt;li&gt;jobsummary&lt;/li&gt;
  &lt;li&gt;reportal&lt;/li&gt;
  &lt;li&gt;pigvisualizer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;安装比较简单，其它解压到plugins/viewer既可（hdfsviewer需要改名为hdfs，reportal需要用viewer目录内的内容），最终结构如下&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-base&quot;&gt;tree -L 2 ./plugins/viewer
./plugins/viewer
├── hdfs
│   ├── conf
│   ├── extlib
│   ├── lib
│   └── package.version
├── javaviewer
│   ├── conf
│   ├── extlib
│   ├── lib
│   ├── package.version
│   └── web
├── jobsummary
│   ├── conf
│   ├── extlib
│   ├── lib
│   ├── package.version
│   └── web
├── pigvisualizer
│   ├── conf
│   ├── extlib
│   ├── lib
│   ├── package.version
│   └── web
└── reportal
    ├── conf
    ├── lib
    └── web
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果Hadoop启用了安全验证，注意设置插件中conf目录下的配置文件到对应的版本，并复制对应的jar包到对应插件的lib里面，找不到就去其它插件里面找找。&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;py&quot;&gt;hadoop.security.manager.class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.security.HadoopSecurityManager_H_1_0&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# hadoop.security.manager.class=azkaban.security.HadoopSecurityManager_H_2_0
# azkaban-hadoopsecuritymanager-2.2.jar
&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# hadoop.security.manager.class=azkaban.security.HadoopSecurityManager_H_3_0
# azkaban-hadoopsecuritymanager-3.0.0.jar
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;HDFS 和 Reportal 在头部可见，其它几个在几种特定的jobtypes结果中可见。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/azkaban-plugins-install.png&quot; alt=&quot;azkaban-plugins-install&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;exec-server-插件&quot;&gt;exec-server 插件&lt;/h2&gt;

&lt;p&gt;主要配置的是jobtypes，具体配置情况如下&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# jobtypes/common.properties
# jobtypes/commonprivate.properties
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;hadoop.home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/hadoop/home/path&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;hive.home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/hadoop/hive/path&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;pig.home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/hadoop/pig/path&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;spark.home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/hadoop/spark/path&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# jobtypes/hadoopJava 默认值
&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# jobtypes/hive/private.properties
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jobtype.class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.jobtype.HadoopHiveJob&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;hive.aux.jar.path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${hive.home}/aux/lib&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jobtype.classpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${hadoop.home}/conf,${hadoop.home}/lib/*,${hive.home}/lib/*,${hive.home}/conf,${hive.aux.jar.path}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# jobtypes/java 默认值
&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pig使用对应版本，高于0.12使用0.12
# jobtypes/pig-0.12.0/plugin.properties
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;pig.listener.visualizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jobtype.classpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${pig.home}/lib/*,${pig.home}/*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# jobtypes/pig-0.12.0/private.properties
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jobtype.class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.jobtype.HadoopPigJob&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jobtype.classpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${hadoop.home}/conf,${hadoop.home}/lib/*,lib/*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# jobtypes/saprk 里少azkaban-jobtype-3.0.0.jar，从别的插件里copy过来
# jobtypes/spark/private.properties
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jobtype.class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.jobtype.HadoopSparkJob&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;hadoop.classpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${hadoop.home}/lib&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jobtype.classpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${hadoop.classpath}:${spark.home}/conf:${spark.home}/jars/*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;reportal 插件里面目录和配置文件，请合并到 jobtypes 内，具体配置文件参照 jobtypes 里对应的插件。&lt;/p&gt;
</description>
                <pubDate>Fri, 08 Sep 2017 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/bigdata/2017/09/08/azkaban3-plugins-installation-and-configuration/</link>
                <guid isPermaLink="true">http://zeyulee.com/bigdata/2017/09/08/azkaban3-plugins-installation-and-configuration/</guid>
            </item>
        
            <item>
                <title>Azkaban 3的安装与配置</title>
                <description>&lt;p&gt;本次Azkaban以3.34源代码为基础进行编译安装 &lt;a href=&quot;https://github.com/azkaban/azkaban/tree/3.34.0&quot;&gt;Github地址&lt;/a&gt;，编译时需要使用gradle，需要Java 8及以上版本。&lt;/p&gt;

&lt;h1 id=&quot;编译&quot;&gt;编译&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/azkaban/azkaban.git

&lt;span class=&quot;c&quot;&gt;# 编译&lt;/span&gt;
./gradlew build

&lt;span class=&quot;c&quot;&gt;# 清理并编译（上次编译失败时执行）&lt;/span&gt;
./gradlew clean

&lt;span class=&quot;c&quot;&gt;# 跳过测试进行编译（会快一些）&lt;/span&gt;
./gradlew build &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;gradlew 下载比较慢，可以从 gradle/wrapper/gradle-wrapper.properties 里面找到下载地址，提前下载好，执行一次编译命令并中断后，放在 $HOME/.gradle/wrapper/dists/gradle-{version}-all/{folder}&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cp ./&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/build/distributions/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz /install/path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;配置&quot;&gt;配置&lt;/h1&gt;

&lt;h2 id=&quot;单机模式&quot;&gt;单机模式&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 解压&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-zxvf&lt;/span&gt; azkaban-solo-server-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz

&lt;span class=&quot;c&quot;&gt;# 目录结构如下&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# bin      执行脚本&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# conf     配置文件&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lib      依赖库，自带了mysql-connector不需要下载了&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# plugins  插件&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# projects 执行job时，任务存放目录（系统会自动创建，请无视）&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# web      前台页面&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# logs     日志（需要新建，为了方便管理日志）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;主配置文件-azkabanproperties&quot;&gt;主配置文件 azkaban.properties&lt;/h3&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Azkaban 个性化设置，除了时区和web资源路径需要注意，其它随意
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;azkaban.name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Test&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;My Local Azkaban&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#FF3601
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.default.servlet.path=/index&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;web.resource.dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;web/&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;default.timezone.id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Asia/Shanghai&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban 用户管理设置，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;user.manager.class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban.user.XmlUserManager&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;user.manager.xml.file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;conf/azkaban-users.xml&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban 项目的设置，默认值
# 所有job参数的父类，覆盖关系见下表
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;executor.global.properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;conf/global.properties&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 执行job时任务存放目录
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;azkaban.project.dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;projects&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 数据库配置
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;database.type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;h2&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;h2.path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;./h2&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;h2.create.tables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Velocity dev mode，官网里没介绍这个参数，也没去研究，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;velocity.dev.mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban 服务器设置，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jetty.use.ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jetty.maxThreads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;25&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;jetty.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;8081&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban 执行服务器端口，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;executor.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;12321&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 邮件设置（【坑1】由于需要支持tls并修改port，这里折腾了很久）
# port和tls官方文档里虽然没说，源码里面是支持的，25和false是默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;mail.sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mail.host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mail.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;25&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mail.tls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mail.user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mail.password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 任务通知邮件（【坑2】官方文档没有一点儿说明，不看源码肯定不知道）
# 这里配置了也没用，看了源码，至少在job里面设置了才能收到邮件
# job.failure.email=
# job.success.email=
# job.notify.email=
&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 非 admin 账户对项目的创建及job上传权限，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;lockdown.create.projects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;lockdown.upload.projects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 缓存目录
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;cache.directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;cache&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# JMX stats，默认值
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;jetty.connector.stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;executor.connector.stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban jobtypes 插件设置，默认值
# 涉及 executor 的插件配置起来都比较麻烦，后面有一篇博客专门说插件配置
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;azkaban.jobtype.plugin.dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;plugins/jobtypes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;参数覆盖关系&quot;&gt;参数覆盖关系&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数来源&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
      &lt;th&gt;优先级&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;global.properties（conf）&lt;/td&gt;
      &lt;td&gt;所有job类型&lt;/td&gt;
      &lt;td&gt;0（最低）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;common.properties（jobtype）&lt;/td&gt;
      &lt;td&gt;所有job类型&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;plugin.properties（jobtype/{jobtype-name}）&lt;/td&gt;
      &lt;td&gt;某一种job类型&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;common.properties（job zip file）&lt;/td&gt;
      &lt;td&gt;某一个job所有环节&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;工作流属性&lt;/td&gt;
      &lt;td&gt;从UI或Ajax执行的job&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;{job-name}.job&lt;/td&gt;
      &lt;td&gt;某一个job内的配置&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;用户配置文件-azkaban-usersxml&quot;&gt;用户配置文件 azkaban-users.xml&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!--权限分 READ,WRITE,EXECUTE,SCHEDULE,CREATEPROJECTS,ADMIN 一级比一级高--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!--某个人的权限 = 角色 + 组，下面是我测试时配置的--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;azkaban-users&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;groups=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;azkaban&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;azkaban&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;username=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;azkaban&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;groups=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;username=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;groups=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_leader&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_leader&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;username=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_leader&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;groups=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_inspector&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_inspector&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;username=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_inspector&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;azkaban&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_leader&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;leader&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_inspector&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;inspector&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;group_schedule&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;roles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ADMIN&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metrics&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;METRICS&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;leader&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;READ,WRITE,EXECUTE,SCHEDULE,CREATEPROJECTS&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;inspector&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;READ&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;write&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WRITE&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;execute&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EXECUTE&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;schedule&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SCHEDULE&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;role&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;createprojects&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;permissions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CREATEPROJECTS&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/azkaban-users&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;./conf/global.properties 和 ./plugins/jobtypes/commonprivate.properties 使用默认值即可。需要对 execute.as.user 进行修改的请参照官网 &lt;a href=&quot;http://azkaban.github.io/azkaban/docs/latest/#azkaban-plugin-configuration&quot;&gt;Plugin Configurations&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;启动&quot;&gt;启动&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 启动&lt;/span&gt;
./bin/azkaban-solo-start.sh
&lt;span class=&quot;c&quot;&gt;# 关闭&lt;/span&gt;
./bin/azkaban-solo-shutdown.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;看不到 &lt;a href=&quot;http://localhost:8081&quot;&gt;UI界面&lt;/a&gt;，请看logs里的报错&lt;/p&gt;

&lt;h2 id=&quot;多机模式&quot;&gt;多机模式&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# web-server&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-zxvf&lt;/span&gt; azkaban-web-server-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz
&lt;span class=&quot;c&quot;&gt;# executor-server&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-zxvf&lt;/span&gt; azkaban-executor-server-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz
&lt;span class=&quot;c&quot;&gt;# 建表语句&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-zxvf&lt;/span&gt; azkaban-db-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.tar.gz

&lt;span class=&quot;c&quot;&gt;# 目录结构同单机基本相同，executor不需要web目录&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mysql数据库&quot;&gt;Mysql数据库&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Mysql&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;数据库初始化&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;在启动时会向&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;executors&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;表插入记录，但默认是不启用，需要修改&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;【坑&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;】如果这里不改，每次&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;启动都要手动设置为&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;，非常不便&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`executors`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHANGE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`active`&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`active`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TINYINT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;web-server-主配置文件-azkabanproperties&quot;&gt;web-server 主配置文件 azkaban.properties&lt;/h3&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 仅列出于单机模式的不同
# 数据库配置
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;database.type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3306&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;localhost&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.numconnections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;100&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 多executor调度规则设置
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;azkaban.use.multiple.executors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.executorselector.filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;StaticRemainingFlowSize,MinimumFreeMemory,CpuStatus&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.executorselector.comparator.NumberOfAssignedFlowComparator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.executorselector.comparator.Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.executorselector.comparator.LastDispatched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;azkaban.executorselector.comparator.CpuUsage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;executor-server-主配置文件-azkabanproperties&quot;&gt;executor-server 主配置文件 azkaban.properties&lt;/h3&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 相比web-server配置很简单
# 数据库配置
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;database.type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3306&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;localhost&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;azkaban&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mysql.numconnections&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;100&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 下面都是默认值
# Azkaban Executor settings
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;executor.maxThreads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;50&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;executor.port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;12321&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;executor.flow.threads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;30&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban JobTypes Plugins
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;azkaban.jobtype.plugin.dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;plugins/jobtypes&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Azkaban the parent for all jobs
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;executor.global.properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;conf/global.properties&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;启动-1&quot;&gt;启动&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 必须先启动executor-server，否则web-server会报找不到executor的错误&lt;/span&gt;
./bin/start-exec.sh
./bin/start-web.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;job-demo&quot;&gt;job demo&lt;/h3&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# foo.job
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;command&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;echo &quot;foo&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# bar.job
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;command&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;echo &quot;bar&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;打包成zip格式文件，新建项目后上传进行测试&lt;/p&gt;
</description>
                <pubDate>Wed, 06 Sep 2017 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/bigdata/2017/09/06/azkaban3-installation-and-configuration/</link>
                <guid isPermaLink="true">http://zeyulee.com/bigdata/2017/09/06/azkaban3-installation-and-configuration/</guid>
            </item>
        
            <item>
                <title>站点网络架构示意图</title>
                <description>&lt;p&gt;日常工作中经常有开发的小伙伴不清楚运维嘴里的常用术语，导致反馈问题表述不准确，判断网络故障也没有一个清晰的思路，有事儿没事儿就甩给运维。作为一个经常跟运维混迹在一起的coder，实在忍受不了运维的吐槽，今天给公司小伙伴从运维的视角讲了讲网站的络架构，下面是用到的示意图（Drew By &lt;a href=&quot;https://www.processon.com&quot;&gt;ProcessOn&lt;/a&gt;）&lt;/p&gt;

&lt;p&gt;主要的知识点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;基础：&lt;a href=&quot;https://zh.wikipedia.org/wiki/OSI%E6%A8%A1%E5%9E%8B&quot;&gt;OSI模型&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;数据链接层：&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%9C%B0%E5%9D%80%E8%A7%A3%E6%9E%90%E5%8D%8F%E8%AE%AE&quot;&gt;ARP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;网络层：&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%BD%91%E9%99%85%E5%8D%8F%E8%AE%AE&quot;&gt;IP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;传输层：&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE&quot;&gt;TCP&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E7%94%A8%E6%88%B7%E6%95%B0%E6%8D%AE%E6%8A%A5%E5%8D%8F%E8%AE%AE&quot;&gt;UDP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;应用层：&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE&quot;&gt;HTTP&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F&quot;&gt;DNS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/network.png&quot; alt=&quot;网络架构图&quot; /&gt;&lt;/p&gt;
</description>
                <pubDate>Thu, 31 Aug 2017 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/training/2017/08/31/website-network-diagram/</link>
                <guid isPermaLink="true">http://zeyulee.com/training/2017/08/31/website-network-diagram/</guid>
            </item>
        
            <item>
                <title>IO密集型应用优化策略</title>
                <description>&lt;p&gt;最近刚刚推广的一个应用，在使用 JMeter 压测过程中出现了性能问题，具体表现为3000并发下 Load-average 和 CPU-Utilization 都不高，JVM内存也没有明显异常，压测结果中有2-5%的请求超过10秒。&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;通过对业务的了解，发现这是一个典型的IO密集型应用（对Redis的只读操作）。前端为Nginx，后端用Resin作为WebServer，代码中配置了连接池（最大连接数为1000，最大空闲连接为500），Redis服务器中查看的来自这个服务的连接数与连接池配置相同，且远没有达到Redis连接数的上限。netstat -s&lt;/td&gt;
      &lt;td&gt;grep -i listen 观察到压测期间，队列长度一直在大量增常，很多请求没有被正常处理。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;从 Nginx、Resin、JVM、Linux 4个方面下手，对涉及到网络和进程数量的部分参数进行调整，以提高处理能力增加队列长度，降低超时率。&lt;/p&gt;

&lt;h2 id=&quot;nginx&quot;&gt;Nginx&lt;/h2&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 设置为与CPU核心数量一致，before 2
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;worker_processes&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;;
# 增加单进程最大并发连接，before 1024
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;worker_connections&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;65535&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resin&quot;&gt;Resin&lt;/h2&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# before 4000
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;accept-listen-backlog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;8192&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# before no set
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;accept-thread-min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;256&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# before 10
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;accept-thread-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;512&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# defore 100
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;keepalive-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;256&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# before 1024
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;thread-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2048&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# defore 20
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;thread-idle-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;512&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# defore 10
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;thread-idle-min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;256&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;jvm&quot;&gt;JVM&lt;/h2&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 没有复杂的递归操作，留出更多的内存创建子线程 defore 512k
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;xss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;128k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;/h2&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/sysctl.conf
# 未完成三次握手的连接队列长度
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;net.ipv4.tcp_max_syn_backlog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;8192&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# TIME-WAIT 连接重用
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;net.ipv4.tcp_tw_reuse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 已完成三次握手等待的队列长度
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;net.core.somaxconn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;20480&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 网卡队列长度
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;net.core.netdev_max_backlog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;51200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;复测超时问题消失，负载和cpu使用率明显上升。&lt;/p&gt;
</description>
                <pubDate>Tue, 04 Jul 2017 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/network/2017/07/04/IO-intensive-application-optimization-strategy/</link>
                <guid isPermaLink="true">http://zeyulee.com/network/2017/07/04/IO-intensive-application-optimization-strategy/</guid>
            </item>
        
            <item>
                <title>PHP7升级全过程记录</title>
                <description>&lt;p&gt;关于PHPNG的计划，在2014年初社区就有讨论，自己也是从那个时候开始，关注着这个里程碑版本的一举一动，毕竟上一次主版本号级的发布还是在遥远的2004年。14年底鸟哥的一篇博文&lt;a href=&quot;http://www.laruence.com/2014/12/18/2976.html&quot;&gt;“PHP7 VS HHVM”&lt;/a&gt;，为开发者展示了PHP7的巨大性能提升。又经过一年漫长的等待，终于在2015年的圣诞节前，迎来了PHP7的第一个正式发布版。&lt;/p&gt;

&lt;p&gt;作为一个极端业务导向的二线公司，受限于技术积累和人力资源，我们把升级的时间初步定在正式发布的1年后。由于还有一些历史问题需要处理，所以分为2个大的阶段：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;第一阶段（2016.4 ～ 2016.8）
    &lt;ul&gt;
      &lt;li&gt;升级PHP版本到5.6，处理历史遗留问题（Mysql、Mssql向PDO迁移，更换mysqlnd）&lt;/li&gt;
      &lt;li&gt;统一生产环境（RedHat 5.8 =&amp;gt; CentOS 6.5，制作RPM标准包，统一发布方式）&lt;/li&gt;
      &lt;li&gt;在统一后的生产环境进行5.6的灰度发布，逐步安排上线&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;第二阶段（2016.12 ～ 2017.3）
    &lt;ul&gt;
      &lt;li&gt;了解PHP7原理&lt;/li&gt;
      &lt;li&gt;运行环境搭建，benchmark 测试&lt;/li&gt;
      &lt;li&gt;处理语法兼容工作，测试并修复bug&lt;/li&gt;
      &lt;li&gt;灰度发布&lt;/li&gt;
      &lt;li&gt;上线&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;业务的选择上，我们选取了移动站点作为试点，主要从这几个因素进行的考量：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;项目新：2013年开坑，2015年经历了一次从5.3到5.5的升级&lt;/li&gt;
  &lt;li&gt;了解深：前后跟了这个项目2年多&lt;/li&gt;
  &lt;li&gt;流量大：每天处理大几千万请求，高峰时勉强过亿&lt;/li&gt;
  &lt;li&gt;有发展：移动化的红利还在&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;实践&quot;&gt;实践&lt;/h1&gt;

&lt;h2 id=&quot;benchmark&quot;&gt;Benchmark&lt;/h2&gt;

&lt;p&gt;测试使用的是官方提供的脚本 &lt;a href=&quot;https://github.com/php/php-src/blob/master/Zend/bench.php&quot;&gt;bench.php&lt;/a&gt;，简单的从执行时间上比较了一下（执行10次），效果惊人。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/php56-php70-benchtime.png&quot; alt=&quot;php56 to php70 benchtime&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2015年从 PHP5.3 升级到 PHP5.5 也测试过一次，速度提升比这个小多了，不过内存占用下降了很多。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/php53-php55-benchtime.png&quot; alt=&quot;php53 to php55 benchtime&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/php53-php55-benchmemory.png&quot; alt=&quot;php53 to php55 benchmemory&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;源码部分&quot;&gt;源码部分&lt;/h2&gt;

&lt;p&gt;我们在运行环境准备的时候，PHP已经发布到了7.0.14，使用的扩展（memcached、redis、xdebug、pthreads等）基本都有了至少一个稳定版本，除了第一次忘了用GCC 4.8+编译，在整个编译过程中也没有遇到问题。开发的扩展代码量很少，只是对几个常用处理过程用C进行了封装。参照&lt;a href=&quot;https://wiki.php.net/phpng-upgrading&quot;&gt;wiki&lt;/a&gt;给出的指引，再结合编译过程中的错误提示，很快就解决了问题。&lt;/p&gt;

&lt;p&gt;通过对比阅读 PHP7 和 PHP5 的源码，发现其之所以在保证兼容性的情况下还能达到很好的性能，主要的优化点在以下几个方面：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MAKE_STD_ZVAL 从栈上分配 zval，减少一次内存读取&lt;/li&gt;
  &lt;li&gt;Hashtable 中使用 arData 直接存储数据，内存使用更加高效&lt;/li&gt;
  &lt;li&gt;字符串结构体 _zend_string 存储了 hash 值，在数组中对字符串 key 的查找时减少一次 hash 计算&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;zval&quot;&gt;zval&lt;/h3&gt;

&lt;p&gt;PHP7 对 zval 结构体改变很大，之前的处理方式是type表示值的类型，变量的值存储在 zvalue_value 联合体中，is_ref__gc 和 refcount__gc 表示是否引用和引用计数器。这种方式有2个比较大的缺点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;占用内存多，实际使用中对象类型的变量少，zend_object_value 可以换成指针&lt;/li&gt;
  &lt;li&gt;结构体没有预留自定义的字段，扩展起来不方便&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zval_struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zvalue_value&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_uint&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;refcount__gc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;is_ref__gc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zvalue_value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;lval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;HashTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_object_value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zvalue_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PHP7 的 zval 结构体包含 zend_value 用于存储变量的值（long or double）或者指针，另外还有 u1 和 u2 两个联合体，u1 是 zval 类型信息（共17种类型，见下zval.u1.type），u2 是辅助信息。另外，引用计数是在 zend_value 而不是 zval 上，变量之间的传递、赋值主要也是对 zend_value，新的做法显然更好一些。&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zval_struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_value&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;cm&quot;&gt;/* value */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;ZEND_ENDIAN_LOHI_4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;         &lt;span class=&quot;cm&quot;&gt;/* active type */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;type_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;const_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;cm&quot;&gt;/* call info for EX(This) */&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;var_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;cm&quot;&gt;/* hash collision chain */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;cache_slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;cm&quot;&gt;/* literal cache slot */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;cm&quot;&gt;/* line number (for ast nodes) */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;num_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;cm&quot;&gt;/* arguments number for EX(This) */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;fe_pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;cm&quot;&gt;/* foreach position */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;fe_iter_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;cm&quot;&gt;/* foreach iterator index */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;access_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/* class constant access flags */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;property_guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* single property guard */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* not further specified */&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zend_value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_long&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;lval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* long value */&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;dval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;cm&quot;&gt;/* double value */&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_refcounted&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_string&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_array&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_object&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_resource&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_reference&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_ast_ref&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zval&lt;/span&gt;             &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;             &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_class_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_function&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ww&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zend_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* zval.u1.type */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* regular data types */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define IS_UNDEF                    0
#define IS_NULL                     1
#define IS_FALSE                    2
#define IS_TRUE                     3
#define IS_LONG                     4
#define IS_DOUBLE                   5
#define IS_STRING                   6
#define IS_ARRAY                    7
#define IS_OBJECT                   8
#define IS_RESOURCE                 9
#define IS_REFERENCE                10
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* constant expressions */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define IS_CONSTANT                 11
#define IS_CONSTANT_AST             12
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* fake types */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define _IS_BOOL                    13
#define IS_CALLABLE                 14
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* internal types */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define IS_INDIRECT                 15
#define IS_PTR                      17
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;hashtable&quot;&gt;HashTable&lt;/h3&gt;

&lt;p&gt;PHP5 的 HashTable 结构体中，数据存储在 arBuckets 指针数组中，它是由 bucket 组成的双向链表，每个元素的值（zval结构）也存在这些 bucket 中，每个 bucket 中保存一个指向 zval 结构的指针，由于老的实现过于考虑通用性，所以不止需要一个指针，而是两个指针。这种结构下 bucket 和 zval 都需要分开分配，分配效率比较低。&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_hashtable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nTableSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nTableMask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nNumOfElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ulong&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nNextFreeElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pInternalPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pListHead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pListTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arBuckets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dtor_func_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pDestructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;persistent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nApplyCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bApplyProtection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;#if ZEND_DEBUG
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inconsistent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bucket&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ulong&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uint&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nKeyLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pDataPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pListNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pListLast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bucket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pLast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/basic_hashtable.png&quot; alt=&quot;HashTable&quot; /&gt;&lt;/p&gt;

&lt;p&gt;保证插入顺序的 bucket 实现&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/ordered_hashtable.png&quot; alt=&quot;Ordered_HashTable&quot; /&gt;&lt;/p&gt;

&lt;p&gt;PHP7 的 HashTable 结构体中，bucket 是一个条目，zval是直接嵌入bucket结构体中，没有必要单独为他分配内存，也不会产生因内存分配引起的冗余信息，减少了空间浪费。&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zend_array&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_zend_array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_refcounted_h&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;ZEND_ENDIAN_LOHI_4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;nApplyCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;nIteratorsCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;zend_uchar&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;consistency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;nTableMask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;nNumUsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;nNumOfElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;nTableSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;nInternalPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;zend_long&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;nNextFreeElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dtor_func_t&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;pDestructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_Bucket&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;zval&lt;/span&gt;              &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;zend_ulong&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;cm&quot;&gt;/* hash value (or numeric index)   */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;zend_string&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;cm&quot;&gt;/* string key or NULL for numerics */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/*
 * HashTable Data Layout
 * =====================
 *
 *                 +=============================+
 *                 | HT_HASH(ht, ht-&amp;gt;nTableMask) |
 *                 | ...                         |
 *                 | HT_HASH(ht, -1)             |
 *                 +-----------------------------+
 * ht-&amp;gt;arData ---&amp;gt; | Bucket[0]                   |
 *                 | ...                         |
 *                 | Bucket[ht-&amp;gt;nTableSize-1]    |
 *                 +=============================+
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;php代码部分&quot;&gt;PHP代码部分&lt;/h2&gt;

&lt;h3 id=&quot;引入composer&quot;&gt;引入Composer&lt;/h3&gt;

&lt;p&gt;以前的程序中使用了很多第三方库（smarty2、phpexcel、phpmailer、qrcode等），有一些用的版本比较老，升级PHP7的过程中也需要同步进行升级。为了将来的考虑，这次做的彻底一些，用&lt;a href=&quot;http://www.phpcomposer.com/&quot;&gt;Composer&lt;/a&gt;来管理第三方库，一些实在找不到替代品的只能自己处理了。现在再看这一步，真应该在升级5.6解决历史包袱的时候就应该处理掉，测试的工作量会少很多。&lt;/p&gt;

&lt;h3 id=&quot;使用openssl替代mcrypt&quot;&gt;使用openssl替代mcrypt&lt;/h3&gt;

&lt;p&gt;吃过上面亏，后面再动手前先看了看刚发布的 PHP7.1 迁移手册中&lt;a href=&quot;http://php.net/manual/zh/migration71.deprecated.php&quot;&gt;废弃的特性&lt;/a&gt;一节，准备比较一下 openssl 和 mcrypt。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/36571743/openssl-or-mcrypt-openssl-encrypt-or-mcrypt-encrypt&quot;&gt;OpenSSL or Mcrypt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/jgosling/articles/4733417.html&quot;&gt;PHP 中 OpenSSL 与 Mcrypt 加密算法效率比较&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;通过上面两篇文章的介绍，openssl 作为 mcrypt 替代者不论从支持的加密种类还是加密速度上都完爆后者。自己经过测试验证，确认无误。替换方式也很简单，这里以 DES-CBC 为例。&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$pad&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$pad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;base64_encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mcrypt_encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MCRYPT_DES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MCRYPT_MODE_CBC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;openssl_encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'DES-CBC'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OPENSSL_ZERO_PADDING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;另外最后提一下，特别是在跨平台时，填充方式可能有的区别，有兴趣的可以看看&lt;a href=&quot;https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding&quot;&gt;这里&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;错误和异常处理&quot;&gt;错误和异常处理&lt;/h3&gt;

&lt;p&gt;set_exception_handler() 不再保证收到的一定是 Exception 对象&lt;/p&gt;

&lt;p&gt;抛出 Error 对象时，如果 set_exception_handler() 里的异常处理代码声明了类型 Exception ，将会导致 fatal error。&lt;/p&gt;

&lt;p&gt;想要异常处理器同时支持 PHP5 和 PHP7，应该删掉异常处理器里的类型声明。如果代码仅仅是升级到 PHP7，则可以把类型 Exception 替换成 Throwable。&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// PHP 5 时代的代码将会出现问题
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set_exception_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'handler'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 兼容 PHP 5 和 7
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 仅支持 PHP 7
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Throwable&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/php_error_reporting_changes.png&quot; alt=&quot;警告级别变更&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;其它细碎变更&quot;&gt;其它细碎变更&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//有变化
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//移除
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;call_user_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;call_user_method_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;ereg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//ereg整个系列函数
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HTTP_RAW_POST_DATA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参数优化&quot;&gt;参数优化&lt;/h2&gt;

&lt;h3 id=&quot;opcache&quot;&gt;Opcache&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enable_cli&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;interned_strings_buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//php文件多可以设置的大一些
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max_accelerated_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8000&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;memory_consumption&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//文件检查周期，追求性能的在生产环境可以关闭，关闭后修改文件必须重启php-fpm才能生效
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;revalidate_freq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fast_shutdown&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//开启hugepages支持
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;opcache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;huge_code_pages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;opcache.file_cache这个还属于实验性质，在生产环境没有启用。&lt;/p&gt;

&lt;h3 id=&quot;hugepages&quot;&gt;HugePages&lt;/h3&gt;

&lt;p&gt;开启系统的HugePages&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sysctl vm.nr_hugepages&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;512

&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;Huge /proc/meminfo
AnonHugePages:    391168 kB
HugePages_Total:     512
HugePages_Free:      477
HugePages_Rsvd:      103
HugePages_Surp:        0
Hugepagesize:       2048 kB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在第一次部署生产环境的时候还遇到了命令行下报错的情况。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/usr/local/php/bin/php &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
PHP Warning: Zend OPcache huge_code_pages: mmap&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HUGETLB&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; failed: Cannot allocate memory &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;12&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;Unknown on line 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;看了一下 text 段的占用，需要5个 HugePages，再看 HugePages_Free 发现只剩下4个了。调整参数到1024并重启 php-fpm，问题解决。出现这个问题主要是生产环境的 php-fpm 进程开的很多，导致 HugePages 不够用了。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;size /usr/local/php/bin/php
   text	   data	    bss	    dec	    hex	filename
11092574	 778968	 149160	12020702	 b76bde	/usr/local/php/bin/php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;分享一个查看进程 HugePages 占用的脚本&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#进程hugepage占用，Redhat&amp;amp;CentOS首选&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-B&lt;/span&gt; 11 &lt;span class=&quot;s1&quot;&gt;'KernelPageSize:     2048 kB'&lt;/span&gt; /proc/[pid]/smaps | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^Size:&quot;&lt;/span&gt; | awk &lt;span class=&quot;s1&quot;&gt;'{sum+=$2} END{print sum/1024}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-perl highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/perl&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#查看huge_pages占用&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sub &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;counthugepages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$pid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;NUMAMAPS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/proc/$pid/numa_maps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;die&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;can't open numa_maps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HUGEPAGECOUNT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;&amp;lt;NUMAMAPS&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/huge.*dirty=(\d+)/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;$HUGEPAGECOUNT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;NUMAMAPS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HUGEPAGECOUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%d huge pages\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;counthugepages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ARGV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;结果&quot;&gt;结果&lt;/h2&gt;

&lt;p&gt;从3月中旬第一次灰度上线，到7月12日下午最后一台服务器升级完成。整个集群CPU使用率平均下降15% - 20%，负载也有很大程度的下降，完全达到预期。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/after-upgrade-cpu.png&quot; alt=&quot;php7升级后cpu使用率情况&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ot41apokn.bkt.clouddn.com/after-upgrade-load.png&quot; alt=&quot;php7升级后负载情况&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;首先要感谢PHP社区各位成员的努力，让PHP的性能有了一次巨大提升，并且这次提升对于大多数应用领域的开发者来说，几乎可以算是透明的。&lt;/p&gt;

&lt;p&gt;在这次漫长的升级过程中，各位小伙伴也为这次里程碑式的升级贡献了太多的智慧，付出了辛勤的劳动，感谢各位。&lt;/p&gt;

&lt;p&gt;接下来还要推动公司内其它老项目的升级工作，希望其他小伙伴也能尽快享受到升级带来的实惠。&lt;/p&gt;

&lt;h1 id=&quot;参考资料&quot;&gt;参考资料&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://www.phpinternalsbook.com/index.html&quot;&gt;PHP Internals Book&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/laruence/php7-internal&quot;&gt;laruence/php7-internal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html&quot;&gt;PHP’s new hashtable implementation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.jobbole.com/103322/&quot;&gt;日请求亿级的 QQ 会员 AMS 平台 PHP7 升级实践&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt&quot;&gt;hugetlbpage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://yong321.freeshell.org/oranotes/HugePages.txt&quot;&gt;Linux HugePages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://access.redhat.com/solutions/320303&quot;&gt;check for hugepages usage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.laruence.com/2015/12/04/3086.html&quot;&gt;让PHP7达到最高性能的几个Tips&lt;/a&gt;&lt;/p&gt;
</description>
                <pubDate>Thu, 08 Jun 2017 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/php/2017/06/08/upgrade-php7/</link>
                <guid isPermaLink="true">http://zeyulee.com/php/2017/06/08/upgrade-php7/</guid>
            </item>
        
            <item>
                <title>mac选购、开发环境搭建及常用软件推荐</title>
                <description>&lt;p&gt;自己购买并使用MacBook Pro也有一段时间了，不论开会写代码都带着，身边有不少开发的小伙伴表示忍受不了信仰灯的诱惑，想趁着双11狠狠的剁一次手。恰逢15款发布，结合我浅显的使用体验，谈谈自己的感受。&lt;/p&gt;

&lt;h2 id=&quot;选购&quot;&gt;选购&lt;/h2&gt;

&lt;p&gt;Mac定位是一款生产工具（想买来打游戏的还是看看外星人吧），对于一个会陪伴你3年以上，为你创造价值的武器，我个人觉得：在你能力范围内买最好的。&lt;/p&gt;

&lt;p&gt;考虑到我没有视频、游戏和双系统的需要，综合便携性，我自己购买的是13寸的中配版本MacBook Pro（以下简称MBP）。MBP是全球联保的产品，1年内提供电话支持和维修服务。考虑到苹果产品维修价格过高，和其3年以上使用寿命，无脑推荐在购买MBP后再搭配Apple Care服务，可以延长2年的保修，淘宝价格在1100左右，选择可以邮寄序列号及手册的实体版本，不差钱的可以去实体店购买。&lt;/p&gt;

&lt;p&gt;15款MacBook激进的使用了目前还不太普及的Type-C接口，又失去了信仰灯的加成，我个人完全不推荐，更详细的可以看Zealer的&lt;a href=&quot;http://www.zealer.com/post/174.html&quot;&gt;评测&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;准备工作&quot;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;在拿到机器，开始搭建开发环境 or 正式使用之前，请做以下两件事&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;准备一块500G－1T的移动硬盘，苹果系统内置了时光机（Time Machine），支持定时自动备份，如果在使用中出现重大系统问题、笔记本丢失、换新的笔记本，可以非常方便的恢复系统，做到完全的平滑回滚，我用了1年大概使用了600G空间。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;升级操作系统：从我1年的使用经验来看，操作系统升级非常平滑，而且新版一般都有很多不错的功能，使用体验也变化不大。如果你升级系统出现崩溃，请用上面提到的时光机进行恢复，然后去买张彩票吧。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;必备工具&quot;&gt;必备工具&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;番羽土啬工具 &lt;a href=&quot;https://github.com/shadowsocks/shadowsocks-iOS/releases&quot;&gt;ShadowSocks&lt;/a&gt; + 账号，没有双币信用卡、不会搭建vps或嫌麻烦的，可以试试&lt;a href=&quot;http://www.fyzhuji.com/aff.php?aff=1409&quot;&gt;枫叶主机&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;终端工具 &lt;a href=&quot;https://www.iterm2.com/downloads.html&quot;&gt;iterm2&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;搭建环境&quot;&gt;搭建环境&lt;/h2&gt;

&lt;h3 id=&quot;终端工具&quot;&gt;终端工具&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#切换zsh为默认shell&lt;/span&gt;
chsh &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/zsh
&lt;span class=&quot;c&quot;&gt;#完全关闭iTerm后，确认切换是否成功&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#输出 /bin/zsh 就对了&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装 &lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh&quot;&gt;oh-my-zsh&lt;/a&gt; 插件&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;编辑配置文件，选择一个你喜欢的&lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh/wiki/themes&quot;&gt;主题&lt;/a&gt;，开启你需要的&lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh/wiki/plugins&quot;&gt;扩展&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#oh-my-zsh配置文件&lt;/span&gt;
vi ~/.zshrc
&lt;span class=&quot;c&quot;&gt;#扩展配置 plugins=(svn git brew composer)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#主题配置 ZSH_THEME=random 不太确定哪个更适合你的，可以设置为随机&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#所有的修改将在新开的iTerm标签生效&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;包管理器工具&quot;&gt;包管理器工具&lt;/h3&gt;

&lt;p&gt;homebrew是Mac平台下非常棒的包管理工具，对于快速搭建开发环境非常有帮助。我个人在安装前，一般都会先看看homebrew上有没有，个别情况下会使用源码编译安装。&lt;/p&gt;

&lt;p&gt;homebrew安装的包默认在 /usr/local/Cellar/ ，在 /usr/local/opt/ 中通过软链接指向程序安装目录，配置文件一般在 /usr/local/etc/ 。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#以下所有brew操作最好配合番羽土啬工具使用，否则可能会出现下载失败的情况&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#使用方法：开启shadowsocks并配置后，在需要执行的brew命令前，添加ALL_PROXY=socks5://127.0.0.1:1080&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#安装nginx&lt;/span&gt;
brew install nginx

&lt;span class=&quot;c&quot;&gt;#从El Capitain开始，1000以下端口必须以root执行，不带sudo让nginx监听80端口需要调整nginx权限&lt;/span&gt;
chown root:wheel /usr/local/opt/nginx/bin/nginx
chmod u+s /usr/local/opt/nginx/bin/nginx
&lt;span class=&quot;c&quot;&gt;#调整nginx默认端口，改listen值为80，默认为8080端口&lt;/span&gt;
vi /usr/local/etc/nginx/nginx.conf

&lt;span class=&quot;c&quot;&gt;#添加自启动，并开启服务&lt;/span&gt;
cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
&lt;span class=&quot;c&quot;&gt;#检查nginx执行是否正常，有1行以上的结果基本就正常了&lt;/span&gt;
ps aux | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;nginx

&lt;span class=&quot;c&quot;&gt;#安装php及扩展&lt;/span&gt;
brew install homebrew/php/php56 homebrew/php/php56-igbinary homebrew/php/php56-mcrypt homebrew/php/php56-memcached homebrew/php/php56-msgpack homebrew/php/php56-pdo-dblib homebrew/php/php56-redis homebrew/php/php56-xhprof homebrew/php/php56-yaf homebrew/php/composer

&lt;span class=&quot;c&quot;&gt;#添加自启动，并开启服务&lt;/span&gt;
cp /usr/local/opt/php56/homebrew.mxcl.php56.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.php56.plist
&lt;span class=&quot;c&quot;&gt;#检查php执行是否正常&lt;/span&gt;
ps aux | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;php

&lt;span class=&quot;c&quot;&gt;#配置站点（省略）&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#配置完成后可以执行 nginx -t 检查配置文件是否正确，nginx -s reload 重启nginx&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#配置本地硬解，跟windows差不多&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vi /etc/host

&lt;span class=&quot;c&quot;&gt;#写个phpinfo() 检查nginx &amp;amp; php合体是否正确&lt;/span&gt;
vi /usr/local/opt/nginx/html/index.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;用homebrew管理软件&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#更新brew并更新版本库&lt;/span&gt;
brew update
&lt;span class=&quot;c&quot;&gt;#查看过期的软件&lt;/span&gt;
brew outdated
&lt;span class=&quot;c&quot;&gt;#升级单个&lt;/span&gt;
brew upgrade xxxx
&lt;span class=&quot;c&quot;&gt;#升级全部&lt;/span&gt;
brew upgrade
&lt;span class=&quot;c&quot;&gt;#清理过期版本（确认新版本正常后再执行）&lt;/span&gt;
brew cleanup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;配置环境变量&quot;&gt;配置环境变量&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#添加到zsh&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'export PATH=&quot;$(brew --prefix php56)/sbin:$PATH&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'export PATH=&quot;/usr/local/sbin:$PATH&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
 
&lt;span class=&quot;c&quot;&gt;#如果你不打算用zsh，请添加到系统默认的bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'export PATH=&quot;$(brew --prefix php56)/sbin:$PATH&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bash_profile
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'export PATH=&quot;/usr/local/sbin:$PATH&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;常用软件&quot;&gt;常用软件&lt;/h3&gt;

&lt;p&gt;Mac平台也有类似苹果手机的app store，一般称呼为Mac App Store（以下简称MAS）。由于苹果严格的审核政策和抢钱一样的分成策略，很多优秀的软件都没有上架MAS，即使上架到MAS的软件，其更新的实时性上也要差很多。如果能去官网下载，最好去官网。&lt;/p&gt;

&lt;p&gt;除了QQ、微信、Evernote等这些主流免费应用外，以下列出的软件推荐在官网上下载：&lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt;、&lt;a href=&quot;https://filezilla-project.org/&quot;&gt;FileZilla&lt;/a&gt;、&lt;a href=&quot;https://kapeli.com/dash&quot;&gt;Dash&lt;/a&gt;、&lt;a href=&quot;http://www.sequelpro.com/&quot;&gt;Sequel Pro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;剩下的自由发挥吧，这里有个&lt;a href=&quot;https://github.com/hzlzh/Best-App&quot;&gt;榜单&lt;/a&gt;可以参考，另外MAS也有限免和冰点价格，请参考&lt;a href=&quot;http://appshopper.com/&quot;&gt;网站&lt;/a&gt;，碰到不错的价格就入手吧。&lt;/p&gt;

&lt;h2 id=&quot;2017年4月补充&quot;&gt;2017年4月补充&lt;/h2&gt;

&lt;h3 id=&quot;选购-1&quot;&gt;选购&lt;/h3&gt;

&lt;p&gt;2016款有带Touchbar的版本了，目前只有少数应用做了兼容，作为开发人员，没有实体Esc键个人觉得是最大的痛苦。要不要Touchbar的版本以及传说中的渣手感键盘，建议先去实体店体验一下，这里做一个简单对比。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;版本&lt;/th&gt;
      &lt;th&gt;价格&lt;/th&gt;
      &lt;th&gt;接口&lt;/th&gt;
      &lt;th&gt;续航&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;有 touchbar&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
      &lt;td&gt;4 Type-C&lt;/td&gt;
      &lt;td&gt;稍差&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;无 touchbar&lt;/td&gt;
      &lt;td&gt;低&lt;/td&gt;
      &lt;td&gt;2 Type-C&lt;/td&gt;
      &lt;td&gt;稍好&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;homebrew&quot;&gt;homebrew&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#服务管理&lt;/span&gt;
brew services list
brew services start zookeeper
brew services stop zookeeper
brew services restart zookeeper

&lt;span class=&quot;c&quot;&gt;#brew case管理三方软件&lt;/span&gt;
brew cask search firefox
brew cask install java
brew cask uninstall chrome
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;软件&quot;&gt;软件&lt;/h3&gt;

&lt;p&gt;上面说的ss已经好久不更新了，推荐一个新的工具 &lt;a href=&quot;https://github.com/shadowsocks/ShadowsocksX-NG/releases/&quot;&gt;ShadowsocksX-NG&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这一年多自己安装软件，基本与之前推荐的榜单使用感受相同。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.alfredapp.com/powerpack/buy/&quot;&gt;Alfred PowerPack&lt;/a&gt; （workflow缺少官方源和类似brew的管理方式，目前只发现这一个缺点）&lt;/li&gt;
  &lt;li&gt;markdown编辑器 &lt;a href=&quot;https://macdown.uranusjr.com/&quot;&gt;MacDown&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Office全家桶 &lt;a href=&quot;https://www.microsoftstore.com.cn/office/office-365-personal/p/qq2-00000&quot;&gt;Office365&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;解压工具 &lt;a href=&quot;http://www.kekaosx.com/zh-cn/&quot;&gt;Keka&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;密码管理软件 &lt;a href=&quot;https://itunes.apple.com/cn/app/1password/id568903335?mt=8&quot;&gt;1Password&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;邮件客户端 &lt;a href=&quot;https://www.mozilla.org/zh-CN/thunderbird/&quot;&gt;ThunderBird&lt;/a&gt; （以前windows用的就是这个，平滑迁移）&lt;/li&gt;
  &lt;li&gt;系统监控 &lt;a href=&quot;https://bjango.com/mac/istatmenus/&quot;&gt;iStat Menus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;鼠标Tips工具 &lt;a href=&quot;https://itunes.apple.com/cn/app/popclip/id445189367?mt=12&quot;&gt;PopClip&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;工具栏管理 &lt;a href=&quot;https://www.macbartender.com/&quot;&gt;Bartender 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
                <pubDate>Wed, 04 Nov 2015 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/experience/2015/11/04/my-experiences-with-Mac/</link>
                <guid isPermaLink="true">http://zeyulee.com/experience/2015/11/04/my-experiences-with-Mac/</guid>
            </item>
        
            <item>
                <title>对Mysql索引类型的一次重新认识</title>
                <description>&lt;p&gt;今天下午突然收到报警邮件，投票系统的Mysql数据库有大量慢查询，导致前台站点访问出现异常。按图索骥开始进行分析，先看后端站点日志，发现出问题时一个没有启用验证码的投票被刷了，出问题的表是实现防刷功能的内存表，数据量大概有十几万行。先在后台开启验证码，恢复前台站点访问。&lt;/p&gt;

&lt;p&gt;按道理内存表再慢也比MyISAM要快，除了数据不能有效落地之外，没有其它明显的缺点了，应用在防刷功能上最合适了，怎么会出现大面积锁表的情况呢？随着分析的深入，发现自己忽略了一个重要的问题，索引类型对内存表也有至关重要的影响，特别是在QPS比较高的情况下。&lt;/p&gt;

&lt;p&gt;内存表使用的索引默认为HASH，而一般的MyISAM默认则为BTREE。&lt;/p&gt;

&lt;p&gt;由于类型为HASH的索引是以hash以后的值作为键，hash之前的大小关系和hash之后的结果没有必然联系，所以HASH索引仅仅能满足”=”，”IN”和”&amp;lt;=&amp;gt;”查询，不能使用范围查询。简而言之就是与memcache一样的kv存储，不能通过范围查询也是理所当然的了。&lt;/p&gt;

&lt;p&gt;进而可以想到，也有如下问题&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;无法对排序进行优化&lt;/li&gt;
  &lt;li&gt;不能利用部分索引查询&lt;/li&gt;
  &lt;li&gt;不能避免全表扫描&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;建表测试&quot;&gt;建表测试&lt;/h2&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_test`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`index`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENGINE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEMORY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`myisam_test`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`index`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENGINE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyISAM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;范围查询测试&quot;&gt;范围查询测试&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;无法使用&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;索引，对&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_test&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;表进行了一次扫描行数为&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;的全表扫描&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`myisam_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myisam_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使用主键索引，对&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myisam_test&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;表进行了一次扫描行数为&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;的范围查询&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;排序测试&quot;&gt;排序测试&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+----------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+----------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filesort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+----------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;仍然无法使用&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;索引，产生一次全表扫描&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`myisam_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myisam_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使用主键索引&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;联合索引中左前缀测试&quot;&gt;联合索引中左前缀测试&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'firstname1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+------+---------+------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;无法使用联合索引&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`myisam_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'firstname1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myisam_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;可以使用到&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;索引&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果非要对内存表进行范围查询怎么办？当然也不是没有解决办法，Mysql在建索引的时候是可以指定索引类型的。&lt;/p&gt;

&lt;h2 id=&quot;对内存表建立btree索引&quot;&gt;对内存表建立BTREE索引&lt;/h2&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_btree_test`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`id`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`index`&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;`lastname`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;USING&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BTREE&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENGINE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEMORY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;联合索引左前缀&quot;&gt;联合索引左前缀&lt;/h3&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;EXPLAIN&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`memory_btree_test`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`firstname`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'firstname1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;select_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt;             &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possible_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Extra&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SIMPLE&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory_btree_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;    &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;----+-------------+-------------------+------+---------------+-------+---------+-------+------+-------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;总结：&lt;/p&gt;

&lt;p&gt;Mysql的每个存储引擎（MyISAM、InnoDB、Memory）都有它的适用场景，索引类型也不例外，当然更不要说各种产品了（Memcache、Redis等等）。了解了每个产品的应用场景才能更好的帮我们解决实际困难，而不是时不时的给自己添堵。在这次故障上，还是体现了自己的无知，仍需要加强学习。&lt;/p&gt;
</description>
                <pubDate>Mon, 04 Jul 2011 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/mysql/2011/07/04/mysql-memory-table-use-btree-index/</link>
                <guid isPermaLink="true">http://zeyulee.com/mysql/2011/07/04/mysql-memory-table-use-btree-index/</guid>
            </item>
        
            <item>
                <title>Linux常用命令</title>
                <description>&lt;blockquote&gt;
  &lt;p&gt;Linux中非常常用的命令，工作中99%会用到，熟练使用事半功倍&lt;/p&gt;

  &lt;p&gt;参考文献里的几个文章，对于想深入学习Linux的开发人员推荐阅读&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;grep&quot;&gt;grep&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#忽略大小写，显示匹配到内容的及前后各5行内容，并附带行号&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'findme'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5 file

&lt;span class=&quot;c&quot;&gt;#显示没有匹配到内容的行&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'findme'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#在当前目录中递归查询，没有匹配到内容的文件名&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'findme'&lt;/span&gt; ./&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#支持gzip文件的匹配&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Z&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; 5 &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'findme'&lt;/span&gt; file.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;find&quot;&gt;find&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#在给定目录中，寻找访问时间在最近30分钟内的文件，并查看其文件信息&lt;/span&gt;
find path &lt;span class=&quot;nt&quot;&gt;-atime&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-30m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-ls&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#在给定目录的最大深度为2的目录结构中，寻找创建时间在1天以前的文件&lt;/span&gt;
find path &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-ctime&lt;/span&gt; +1d &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f

&lt;span class=&quot;c&quot;&gt;#当前目录下，寻找空文件并删除&lt;/span&gt;
find ./ &lt;span class=&quot;nt&quot;&gt;-empty&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#从给定目录中，按文件名寻找，并执行给定命令&lt;/span&gt;
find path &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'file'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; md5 &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#寻找比给定文件修改时间新的链接&lt;/span&gt;
find path &lt;span class=&quot;nt&quot;&gt;-newer&lt;/span&gt; file &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; l

&lt;span class=&quot;c&quot;&gt;#寻找1MB以下文件&lt;/span&gt;
find path &lt;span class=&quot;nt&quot;&gt;-size&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1M&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f

&lt;span class=&quot;c&quot;&gt;#删除所有失效的链接&lt;/span&gt;
find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; path &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; l &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; rm &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; +

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;sed&quot;&gt;sed&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#打印被替换的行&lt;/span&gt;
sed &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/test/TEST/p'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#显示从第一个表达式到第二个表达式之间的行&lt;/span&gt;
sed &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/^fls/,/^dd/p'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#删除空行&lt;/span&gt;
sed &lt;span class=&quot;s1&quot;&gt;'/^$/d'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#删除第7行到最后一行&lt;/span&gt;
sed &lt;span class=&quot;s1&quot;&gt;'7,$d'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#替换以fml开头的行为fmlgo&lt;/span&gt;
sed &lt;span class=&quot;s1&quot;&gt;'s/^fml/&amp;amp;go/'&lt;/span&gt; file
sed &lt;span class=&quot;s1&quot;&gt;'s/^\(fml\)/\1go/'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#删除第1到第3行，并进行替换，在结尾附加file2&lt;/span&gt;
sed &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'1,3d'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/^fml/lmf/'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$r file2'&lt;/span&gt; file1

&lt;span class=&quot;c&quot;&gt;#输出奇数行&lt;/span&gt;
sed &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'p;n'&lt;/span&gt; file

&lt;span class=&quot;c&quot;&gt;#输出偶数行&lt;/span&gt;
sed &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'n;p'&lt;/span&gt; file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;awk&quot;&gt;awk&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#平均QPS&lt;/span&gt;
awk &lt;span class=&quot;s1&quot;&gt;'{sec=substr($4,2,20);reqs++;reqsBySec[sec]++;} END{print reqs/length(reqsBySec)}'&lt;/span&gt; nginx.log

&lt;span class=&quot;c&quot;&gt;#最大QPS&lt;/span&gt;
awk &lt;span class=&quot;s1&quot;&gt;'{sec=substr($4,2,20);reqsBySec[sec]++;} END{for(s in reqsBySec){printf(&quot;%s %s\n&quot;, reqsBySec[s], s)}}'&lt;/span&gt; nginx.log | sort &lt;span class=&quot;nt&quot;&gt;-nr&lt;/span&gt; | head &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 3

&lt;span class=&quot;c&quot;&gt;#单个url最大体积&lt;/span&gt;
awk &lt;span class=&quot;s1&quot;&gt;'{url=$7;size[url]+=$10} END{for(s in size){printf(&quot;%s %s\n&quot;,size[s],s)}}'&lt;/span&gt; nginx.log | sort &lt;span class=&quot;nt&quot;&gt;-nr&lt;/span&gt; | head &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 5

&lt;span class=&quot;c&quot;&gt;#带宽&lt;/span&gt;
awk &lt;span class=&quot;s1&quot;&gt;'{sec=substr($4,2,20);size[sec]+=$10} END{for(s in size){printf(&quot;%sKB %s\n&quot;,size[s]/1024,s)}}'&lt;/span&gt; nginx.log | sort &lt;span class=&quot;nt&quot;&gt;-nr&lt;/span&gt; | head &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;xargs&quot;&gt;xargs&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#批量杀进程&lt;/span&gt;
ps aux | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;php-fpm | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'grep'&lt;/span&gt; | awk &lt;span class=&quot;s1&quot;&gt;'{print $2}'&lt;/span&gt; | xargs &lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-9&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#替换指定位置&lt;/span&gt;
less filenames.txt | axrgs &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; cp &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考文献&quot;&gt;参考文献&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://man.linuxde.net/&quot;&gt;Linux命令大全&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://linuxcommand.org/&quot;&gt;linuxcommand&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.thegeekstuff.com/2010/11/50-linux-commands/&quot;&gt;50 Most Frequently Used UNIX / Linux Commands&lt;/a&gt;&lt;/p&gt;
</description>
                <pubDate>Tue, 21 Dec 2010 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/linux/2010/12/21/linux-commands/</link>
                <guid isPermaLink="true">http://zeyulee.com/linux/2010/12/21/linux-commands/</guid>
            </item>
        
            <item>
                <title>在Smarty里把页面输出压缩成1行</title>
                <description>&lt;p&gt;为了提高页面的加载速度，尝试对输出的html响应内容进行压缩。项目使用的是Smarty作为模版引擎，查了&lt;a href=&quot;http://www.smarty.net/docs/en/api.functions.tpl&quot;&gt;官方手册&lt;/a&gt;是支持过滤器的，三种过滤器区别如下&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;prefilter：编译成php脚本前&lt;/li&gt;
  &lt;li&gt;postfilter：编译成php脚本后&lt;/li&gt;
  &lt;li&gt;outputfilter：显示前&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;考虑到Smarty可能会升级，没有采用loadFilter这种标准扩展方式，而是在工厂类使用注册函数的方式实现。&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_smarty&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Smarty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#Smarty3版本
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_smarty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'output'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'htmlCompress'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#Smarty2版本
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_smarty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register_outputfilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'htmlCompress'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;/**
 * Html代码压缩
 * @param string $tpl_source 模版资源路径
 * @param obj    $smarty     smarty对象
 * @return string
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;htmlCompress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tpl_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$smarty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//这4类情况进行转换：
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;//HTML注释（非贪婪匹配）
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;//连续多个空白
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;//HTML标记之间的空白，如 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 之间的空白
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;//js代码分号结尾后的空白
&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;$patterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/&amp;lt;!--.*--&amp;gt;/U'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/\s+/m'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/&amp;gt;\s+&amp;lt;/m'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/;\s+/m'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$replacements&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;gt;&amp;lt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;';'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$patterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$replacements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$tpl_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;写好了本地一跑js报错一大堆，又改了1个小时的内连js脚本才好。总结一下报错的原因无外乎以下2个，算是一个小坑吧。&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//修改单行注释为块注释&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 这个ok */&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* 结尾一定要写分号 */&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;p.intro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
                <pubDate>Sat, 17 Jul 2010 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/php/2010/07/17/compress-html-to-single-line-in-smarty/</link>
                <guid isPermaLink="true">http://zeyulee.com/php/2010/07/17/compress-html-to-single-line-in-smarty/</guid>
            </item>
        
            <item>
                <title>使用SPL读取大文件</title>
                <description>&lt;p&gt;开发中需要读取一个大文件的指定行，试了很多种方法效果都不太理想，想起前几天翻看PHP手册中提到的SPL好像有能解决问题的办法，尝试了一下成功解决问题。&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;sd&quot;&gt;/**
 * @param $file_name string 文件路径
 * @param $start integer 起始行
 * @param $limit integer 向后读取行数
 * @return array 内容
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SplFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#测试的file.log文件700MB
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$time_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;microtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/path/file.log'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6789&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'in '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;microtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$time_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;' seconds'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#in 0.003400924346561 seconds
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
                <pubDate>Sun, 24 Jan 2010 00:00:00 +0800</pubDate>
                <link>http://zeyulee.com/php/2010/01/24/use-php-spl-read-huge-file/</link>
                <guid isPermaLink="true">http://zeyulee.com/php/2010/01/24/use-php-spl-read-huge-file/</guid>
            </item>
        
    </channel>
</rss>
