2012年11月9日星期五

Job 相同 Unique Key 的处理

测试 1
<?php

$start_time = date('Y-m-d H:i:s');
echo "Start: " . $start_time . "\n";

$gmc= new GearmanClient();
$gmc->addServer();
$gmc->setStatusCallback("reverse_status");
$gmc->setCompleteCallback("reverse_complete");
$gmc->addTask("reverse", "Hi! - $start_time", null, 1);


if (! $gmc->runTasks()) {
    echo "ERROR " . $gmc->error() . "\n";
    exit;
}


function reverse_status($task) {

    echo "STATUS: " . $task->unique() . ", " .
    $task->jobHandle() . " - " .
    $task->taskNumerator() .  "/" .
    $task->taskDenominator() . "\n";
}

function reverse_complete($task) {
    echo "COMPLETE: " . $task->unique() . ", " . $task->data() . "\n";
}
?>
<?php
$gmworker= new GearmanWorker();
$gmworker->addServer();

$gmworker->addFunction("reverse", "reverse_fn");

$flag = true;

while($flag){
    $flag = $gmworker->work();
}


function reverse_fn($job) {
    echo "Received job: " . $job->handle() . "\n";
    $workload = $job->workload();

    $workload_size = $job->workloadSize();
    echo "Workload: $workload ($workload_size)\n";

    # This status loop is not needed, just showing how it works

    for ($x= 0; $x < $workload_size; $x++) {
        echo "Sending status: " . ($x + 1) . "/$workload_size complete\n";

        $job->sendStatus($x+1, $workload_size);
        $job->sendData(substr($workload, $x, 1));
        sleep(1);
    }


    $result= strrev($workload);

    echo "Result: $result\n";

    # Return what we want to send back to the client.

    return $result;
}
?>
开启三个终端,第一个终端运行 worker,另外两个终端运行 client:
[root@www test]# php w-unique.php 
Received job: H:www:641
Workload: Hi! - 2012-11-08 11:01:00 (25)
Sending status: 1/25 complete
Sending status: 2/25 complete
Sending status: 3/25 complete
Sending status: 4/25 complete
Sending status: 5/25 complete
Sending status: 6/25 complete
Sending status: 7/25 complete
Sending status: 8/25 complete
Sending status: 9/25 complete
Sending status: 10/25 complete
Sending status: 11/25 complete
Sending status: 12/25 complete
Sending status: 13/25 complete
Sending status: 14/25 complete
Sending status: 15/25 complete
Sending status: 16/25 complete
Sending status: 17/25 complete
Sending status: 18/25 complete
Sending status: 19/25 complete
Sending status: 20/25 complete
Sending status: 21/25 complete
Sending status: 22/25 complete
Sending status: 23/25 complete
Sending status: 24/25 complete
Sending status: 25/25 complete
Result: 00:10:11 80-11-2102 - !iH

[root@www test]# php c-unique.php 
Start: 2012-11-08 11:01:00
STATUS: 1, H:www:641 - 1/25
STATUS: 1, H:www:641 - 2/25
STATUS: 1, H:www:641 - 3/25
STATUS: 1, H:www:641 - 4/25
STATUS: 1, H:www:641 - 5/25
STATUS: 1, H:www:641 - 6/25
STATUS: 1, H:www:641 - 7/25
STATUS: 1, H:www:641 - 8/25
STATUS: 1, H:www:641 - 9/25
STATUS: 1, H:www:641 - 10/25
STATUS: 1, H:www:641 - 11/25
STATUS: 1, H:www:641 - 12/25
STATUS: 1, H:www:641 - 13/25
STATUS: 1, H:www:641 - 14/25
STATUS: 1, H:www:641 - 15/25
STATUS: 1, H:www:641 - 16/25
STATUS: 1, H:www:641 - 17/25
STATUS: 1, H:www:641 - 18/25
STATUS: 1, H:www:641 - 19/25
STATUS: 1, H:www:641 - 20/25
STATUS: 1, H:www:641 - 21/25
STATUS: 1, H:www:641 - 22/25
STATUS: 1, H:www:641 - 23/25
STATUS: 1, H:www:641 - 24/25
STATUS: 1, H:www:641 - 25/25
COMPLETE: 1, 00:10:11 80-11-2102 - !iH
[root@www test]# php c-unique.php
Start: 2012-11-08 11:01:02
STATUS: 1, H:www:641 - 3/25
STATUS: 1, H:www:641 - 4/25
STATUS: 1, H:www:641 - 5/25
STATUS: 1, H:www:641 - 6/25
STATUS: 1, H:www:641 - 7/25
STATUS: 1, H:www:641 - 8/25
STATUS: 1, H:www:641 - 9/25
STATUS: 1, H:www:641 - 10/25
STATUS: 1, H:www:641 - 11/25
STATUS: 1, H:www:641 - 12/25
STATUS: 1, H:www:641 - 13/25
STATUS: 1, H:www:641 - 14/25
STATUS: 1, H:www:641 - 15/25
STATUS: 1, H:www:641 - 16/25
STATUS: 1, H:www:641 - 17/25
STATUS: 1, H:www:641 - 18/25
STATUS: 1, H:www:641 - 19/25
STATUS: 1, H:www:641 - 20/25
STATUS: 1, H:www:641 - 21/25
STATUS: 1, H:www:641 - 22/25
STATUS: 1, H:www:641 - 23/25
STATUS: 1, H:www:641 - 24/25
STATUS: 1, H:www:641 - 25/25
COMPLETE: 1, 00:10:11 80-11-2102 - !iH
上面是三个终端运行的结果。terminal-2, terminal-3 提交 Job 到 Gearmand Server,terminal-1 做为 worker,执行提交到 Geramand Server 所有为 reverse 的 Job。terminal-2, terminal-3 开始时间不同,但结束时间相同。 Unique ID 相同,先前提交的 Job 没有执行完时,Gearmand 会将同 Unique Key 的 Job 合并,即它们会同时收到相同的执行情况信息:
  1. terminal-2 提交 Job A , worker 接到调度信息立即对 Job A 进行处理。
  2. 在 termial-3 提交相同 Unique Key 的 Job B,两者提交的时差为 2s。
  3. 因为 reverse worker 的运行时间 >= 25s ,所以 Job B 提交时 Job A 实际还处于执行,Gearmand Server 将 Job B 合到 Job A 一起。
  4. terminal-3 收到这时和 terminal-2 相同的 Job Status。
简单理解的话,Gearmand Server 会将 Unique Key 做为每一个 Job 的标识,当提交的 Job 的 Unique Key 相同时,服务器将其第 N (N > 1)个提交的 Job 视为重复提交,直接忽略,不对其进行任何处理。这些逻辑都只针对于当前在队列中的 Job,已经执行完毕的 Job 不会对其进行这样的处理。
测试 2
<?php
$gmc= new GearmanClient();
$gmc->addServer();

for ($i = 0; $i < 11; $i++) {
    $gmc->doBackground("reverse", "Hi! - $i", 1);
}

for ($i = 0; $i < 11; $i++) {
    $gmc->addTaskBackground("reverse", "Hi! - $i", null, 2);
}


if (! $gmc->runTasks()) {
    echo "ERROR " . $gmc->error() . "\n";
    exit;
}
?>
修改 Client,将提交的 Jobs/Tasks 改为是后台处理。假设 Gearmand Server 采用了 MySQL 的持久存储,不启动 reverse worker,只运行上述的 Client 脚本,查询数据库:
mysql> SELECT * FROM gearman_queue;
+------------+---------------+----------+----------+-------------+
| unique_key | function_name | priority | data     | when_to_run |
+------------+---------------+----------+----------+-------------+
| 1          | reverse       |        1 | Hi! - 0  |           0 |
| 2          | reverse       |        1 | Hi! - 10 |           0 |
+------------+---------------+----------+----------+-------------+
2 rows in set (0.04 sec)
从上面得知,尽管 Unqiue Key 为 12 的都提交了 10 次,而队列中对应的记录却都只有一条。也就说明,当 Unique Key 相同时,Gearmand Server 对提交的 Job/Tasks 做了合并处理。
说明:
  • 当然,从Gearmand 队列持久化其表结构中可知,unique_key 做为主键,必须是唯一的,而该值对应 Job 提交时的 Unqiue Key。即在 Unique Key 相同时,在数据库中,记录必定无法添加,即上述 例 1 所要说明的原因 (这里实际上还有点疑问, MySQL/Drizzle 和 sqlite3 的表结构竟然不同,MySQL/Drizzle 表结构竟然是在 unique_key 和 function_name 上做唯一的索引,而 unqiue_key 也没做主键,难道实际中有同 unique_key 而不同 function_name 这样的用法?而且从 MySQL 性能方面来讲,不设置主键似乎也说不过去;如果 engine 采用 InnoDB,内部还是会给建一主键。)。
    CREATE TABLE gearman_queue (    
    unique_key VARCHAR(64),    
    function_name VARCHAR(255),    
    priority INT,    
    data LONGBLOB,    
    when_to_run INT,    
    unique key (unique_key, function_name))    
    
    CREATE TABLE gearman_queue (
    unique_key TEXT PRIMARY KEY,
    function_name TEXT,
    priority INTEGER,
    data BLOB,
    when_to_run INTEGER)
    
  • 在同一个进程里,addTask/addTaskBackground 提交 Tasks 时,因为都是在调用 $gmc->runTasks() 后,所有这个进程里需提交的 Tasks 才提交到 Gearmand Server。而在提交时,如果所有 Tasks 的 Unique Key 相同,后面 Task 调用的参数数据会覆盖前面调用的。 所以,也就有上述查询中 unique_key 2 时处理的数据是 Hi! - 10

Gearman MySQL UDFs

Install


下载 Gearman User Defined Functions for MySQL 最新版。
[bash]
[root@www gearman-mysql-udf-0.6]# ./configure --libdir=/usr/local/mysql/lib/mysql/plugin/ --with-libgearman-prefix=/usr/local/gearmand/ --with-mysql=/usr/local/mysql/bin/mysql_config
[root@www gearman-mysql-udf-0.6]# make
[root@www gearman-mysql-udf-0.6]# make install
[/bash]

说明:

  • 如果 MySQL 是 source code 安装的话,必须使其支持 plugin (加上 --enable-shared配置项,且确保没有 --with-mysqld-ldflags=-all-static配置项),否则在后面步骤中创建函数时,会提示创建失败的提示:
    [sql]
    mysql> CREATE FUNCTION gman_do RETURNS STRING
    -> SONAME "libgearman_mysql_udf.so";
    ERROR 1126 (HY000): Can't open shared library 'libgearman_mysql_udf.so' (errno: 0 feature disabled)
    [/sql]

  • --libdir 确保指向 MySQL server plugin 的目录,即 MySQL plugin_dir 的值。
    [sql]
    mysql> show variables like '%plugin%';
    +---------------+-----------------------------------+
    | Variable_name | Value |
    +---------------+-----------------------------------+
    | plugin_dir | /usr/local/mysql/lib/mysql/plugin |
    +---------------+-----------------------------------+
    1 row in set (0.00 sec)
    [/sql]

  • 如果 Gearman 不是采用默认配置选项安装的话,还需用 --with-libgearman-prefix 指定 Gearman 安装目录。



安装成功的话,在 MySQL plugin 的目录中,应该有如下文件:
[bash]
[root@www gearman-mysql-udf-0.6]# ls -l /usr/local/mysql/lib/mysql/plugin/
total 128
-rwxr-xr-x 1 root root 1059 Oct 31 11:36 libgearman_mysql_udf.la
lrwxrwxrwx 1 root root 29 Oct 31 11:36 libgearman_mysql_udf.so -> libgearman_mysql_udf.so.0.0.0
lrwxrwxrwx 1 root root 29 Oct 31 11:36 libgearman_mysql_udf.so.0 -> libgearman_mysql_udf.so.0.0.0
-rwxr-xr-x 1 root root 111710 Oct 31 11:36 libgearman_mysql_udf.so.0.0.0
[/bash]

修改 plugin 目录的属主和访问权限,登录 MySQL,执行下面查询 :
[sql]
CREATE FUNCTION gman_do RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_do_high RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_do_low RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_do_background RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_do_high_background RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_do_low_background RETURNS STRING
SONAME "libgearman_mysql_udf.so";
CREATE AGGREGATE FUNCTION gman_sum RETURNS INTEGER
SONAME "libgearman_mysql_udf.so";
CREATE FUNCTION gman_servers_set RETURNS STRING
SONAME "libgearman_mysql_udf.so";
[/sql]

Run Job


函数创建完后,调用 gman_server_set 来设置 Gearman 的服务器。
[sql]
mysql> select gman_servers_set('127.0.0.1:4730,127.0.0.1:4731');
+---------------------------------------------------+
| gman_servers_set('127.0.0.1:4730,127.0.0.1:4731') |
+---------------------------------------------------+
| 127.0.0.1:4730,127.0.0.1:4731 |
+---------------------------------------------------+
1 row in set (0.00 sec)
[/sql]

也可以每个函数设置不同的 Gearman Server,如:
[sql]
mysql> select gman_servers_set('127.0.0.1', 'reverse');
+------------------------------------------+
| gman_servers_set('127.0.0.1', 'reverse') |
+------------------------------------------+
| 127.0.0.1 |
+------------------------------------------+
1 row in set (0.00 sec)

mysql> select gman_servers_set('127.0.0.1:4731', 'wc');
+------------------------------------------+
| gman_servers_set('127.0.0.1:4731', 'wc') |
+------------------------------------------+
| 127.0.0.1:4731 |
+------------------------------------------+
1 row in set (0.00 sec)
[/sql]

服务器设置好后,接着通过查询来执行 JOB:
[sql]
mysql> SELECT gman_do('reverse', host) AS test FROM mysql.user;
+----------------+
| test |
+----------------+
| 1: % |
| 2: 1.0.0.721 |
| 3: 1.0.0.721 | |
| 4: tsohlacol |
| 5: tsohlacol |
+----------------+
5 rows in set (2 min 8.43 sec)

mysql> SELECT gman_do('reverse', 'hello, world!');
+-------------------------------------+
| gman_do('reverse', 'hello, world!') |
+-------------------------------------+
| 8: !dlrow ,olleh |
+-------------------------------------+
1 row in set (0.00 sec)
[/sql]


当查询调用的是 gman_do_background() 时,返回的是 job handle,可用其来查询 job 的状态。
[sql]
mysql> SELECT gman_do_background('reverse', 'test1, test2, test3, test4');
+-------------------------------------------------------------+
| gman_do_background('reverse', 'test1, test2, test3, test4') |
+-------------------------------------------------------------+
| H:www:869425 |
+-------------------------------------------------------------+
1 row in set (0.00 sec)
[/sql]

上面例题正常进行的话,除了要启动 JOB Server gearmand外,还需要运行对应的 worker。

gman_do* 开头的函数还提供可选的第三个参数,它们用于做 unique JOB ID。在同时提交多个 JOB 给相同的 unique ID 时,Gearmand 将会在队列中把它们合并到一起,然后一次执行。需要注意的是,Gearmand 仅合并当前在队列中等待/运行 的 JOB,对于已经运行结束的 JOB 的 unique ID ,不会做跟踪处理。


Remove


如果需要移除上述创建的 MySQL UDF,执行下面查询即可:
[sql]
DROP FUNCTION gman_do;
DROP FUNCTION gman_do_high;
DROP FUNCTION gman_do_low;
DROP FUNCTION gman_do_background;
DROP FUNCTION gman_do_high_background;
DROP FUNCTION gman_do_low_background;
DROP FUNCTION gman_sum;
DROP FUNCTION gman_servers_set;
[/sql]

References:
mysql_udf_readme

How To Get System Info In Linux

FROM: How To Get System Info In Linux

General System Info


Note: 大部分获取硬件信息的命令都必须以 root 身份运行,而那些可以以其他身份运行的命令,在以 root 身份运行时,系统会提供更多的信息。


  1. 运行 qtpartedGParted 获取硬盘和分区信息。也可以用 KDiskFreefdisk -l 查看所有的分区信息。

  2. hardinfo,收集系统和硬件信息,生成报告。
    在 Synaptic (Ubuntu 桌面系统包管理器) 包管理器中,hardinfo 是安装 installation-report 包。完成后,在终端窗口运行:
    [bash gutter="false"]
    report-hw
    # 或将报告生成名为 hwreport, 存入 $HOME 目录下的 text 文件
    report-hw > hwreport
    [/bash]

  3. sysinfo 在终端运行,以图形方式展现当前系统的所有统计信息。

  4. hal-device-manager,kde-hal-device-manager 可通过 Synaptic 安装,即 KMenu > System > Device Manager > kde-hal-device-manager。



    • dmidecode -t memory (以 root 身份) dmidecode 工具将导出系统 DMI(Desktop Management Interface) 表。这个表包括系统硬件组件,BIOS 版本信息等。它不仅包括系统当前的配置信息,还包括可支持的 CPU 速度下的 BIOS 限制,允许的最大内存等。

    • dmidecode | less (以 root 身份) 以分页形式查看 BIOS 和 系统信息 (按 space 往下查看,按 q 退出)





    • uname -a 打印详细信息,依次为内核名称,主机名,内核版本号,内核版本,硬件名,处理器类型,硬件平台类型,操作系统名称。

    • uname -m 打印主机硬件名。

    • uname -r 内核版本。


    [bash]
    [root@www ~]# uname -a
    Linux wwww 2.6.27 #1 SMP Fri Oct 15 00:59:47 CST 2010 x86_64 x86_64 x86_64 GNU/Linux
    [root@www ~]# uname -m
    x86_64
    [root@www ~]# uname -r
    2.6.27
    [/bash]



    • lshw (以 root 用户) 以纯文本的格式输出硬件报告,也可生成 html、xml 等格式的报告。可用 lshw | less 分页查看 (space 往下参看, q 退出)

    • lshw-gtk (以 root 用户) 可从 Synaptic 下载安装。在图形界面下查看硬件信息。



  5. lsb_release -a 或查看 /etc/lsb_release.d
    [bash]
    [root@www ~]# lsb_release -a
    LSB Version: :core-3.1-amd64:core-3.1-ia32:core-3.1-noarch:graphics-3.1-amd64:graphics-3.1-ia32:graphics-3.1-noarch
    Distributor ID: CentOS
    Description: CentOS release 5.3 (Final)
    Release: 5.3
    Codename: Final
    [/bash]
    Mepis Linux 6.5 上,登录界面也可查看版本信息。



    • lspci (以 root 身份) 查看 PCI 设备, -v 详细信息, -vv 更多详细信息。

    • lspci -tv (以 root 身份) 以树状形式展示。

    • lsusblsusb -tv 查看 USB 设备的详细信息。

    • lsmod (以 root 身份) 查看目前内核加载的模块,也可用 lsmod | less 分页展示。


    [bash collapse="true"]
    [root@www ~]# lspci
    00:00.0 Host bridge: Intel Corporation X58 I/O Hub to ESI Port (rev 13)
    00:01.0 PCI bridge: Intel Corporation X58 I/O Hub PCI Express Root Port 1 (rev 13)
    00:03.0 PCI bridge: Intel Corporation X58 I/O Hub PCI Express Root Port 3 (rev 13)
    00:07.0 PCI bridge: Intel Corporation X58 I/O Hub PCI Express Root Port 7 (rev 13)
    00:14.0 PIC: Intel Corporation X58 I/O Hub System Management Registers (rev 13)
    00:14.1 PIC: Intel Corporation X58 I/O Hub GPIO and Scratch Pad Registers (rev 13)
    00:14.2 PIC: Intel Corporation X58 I/O Hub Control Status and RAS Registers (rev 13)
    00:1a.0 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #4
    00:1a.1 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #5
    00:1a.7 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2
    00:1d.0 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #1
    00:1d.1 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #2
    00:1d.2 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #3
    00:1d.3 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #6
    00:1d.7 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #1
    00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 90)
    00:1f.0 ISA bridge: Intel Corporation 82801JIR (ICH10R) LPC Interface Controller
    00:1f.2 IDE interface: Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller
    00:1f.5 IDE interface: Intel Corporation 82801JI (ICH10 Family) 2 port SATA IDE Controller
    01:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5716 Gigabit Ethernet (rev 20)
    01:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5716 Gigabit Ethernet (rev 20)
    02:00.0 SCSI storage controller: LSI Logic / Symbios Logic SAS1068E PCI-Express Fusion-MPT SAS (rev 08)
    04:03.0 VGA compatible controller: Matrox Graphics, Inc. MGA G200eW WPCM450 (rev 0a)
    [root@www ~]# lspci -tv
    -[0000:00]-+-00.0 Intel Corporation X58 I/O Hub to ESI Port
    +-01.0-[0000:01]--+-00.0 Broadcom Corporation NetXtreme II BCM5716 Gigabit Ethernet
    | \-00.1 Broadcom Corporation NetXtreme II BCM5716 Gigabit Ethernet
    +-03.0-[0000:02]----00.0 LSI Logic / Symbios Logic SAS1068E PCI-Express Fusion-MPT SAS
    +-07.0-[0000:03]--
    +-14.0 Intel Corporation X58 I/O Hub System Management Registers
    +-14.1 Intel Corporation X58 I/O Hub GPIO and Scratch Pad Registers
    +-14.2 Intel Corporation X58 I/O Hub Control Status and RAS Registers
    +-1a.0 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #4
    +-1a.1 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #5
    +-1a.7 Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2
    +-1d.0 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #1
    +-1d.1 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #2
    +-1d.2 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #3
    +-1d.3 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #6
    +-1d.7 Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #1
    +-1e.0-[0000:04]----03.0 Matrox Graphics, Inc. MGA G200eW WPCM450
    +-1f.0 Intel Corporation 82801JIR (ICH10R) LPC Interface Controller
    +-1f.2 Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller
    \-1f.5 Intel Corporation 82801JI (ICH10 Family) 2 port SATA IDE Controller
    [root@www ~]# lsusb
    Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp.
    Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    [root@www ~]# lsusb -tv
    Bus# 0
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 7
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 6
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 5
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 4
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 3
    `-Dev# 1 Vendor 0x1d6b Product 0x0001
    Bus# 2
    `-Dev# 1 Vendor 0x1d6b Product 0x0002
    Bus# 1
    `-Dev# 1 Vendor 0x1d6b Product 0x0002
    `-Dev# 2 Vendor 0x0424 Product 0x2514
    [root@www ~]#
    [root@www ~]# lsmod
    Module Size Used by
    nfsd 262312 17
    auth_rpcgss 55968 1 nfsd
    exportfs 20928 1 nfsd
    nfs 266032 1
    nfs_acl 19840 2 nfsd,nfs
    lockd 80784 2 nfsd,nfs
    autofs4 36104 2
    hidp 31296 2
    rfcomm 50912 0
    l2cap 36864 10 hidp,rfcomm
    bluetooth 73764 5 hidp,rfcomm,l2cap
    sunrpc 210056 17 nfsd,auth_rpcgss,nfs,nfs_acl,lockd
    ipv6 273320 94
    dm_mirror 32640 0
    dm_log 26244 1 dm_mirror
    dm_multipath 32344 0
    scsi_dh 23748 1 dm_multipath
    dm_mod 71408 3 dm_mirror,dm_log,dm_multipath
    sbs 30160 0
    sbshc 22720 1 sbs
    battery 29192 0
    acpi_memhotplug 22340 0
    ac 21640 0
    parport_pc 43496 0
    lp 27844 0
    parport 53872 2 parport_pc,lp
    sg 48864 0
    dcdbas 24240 0
    sr_mod 31748 0
    cdrom 49768 1 sr_mod
    serio_raw 22276 0
    button 23968 0
    rtc_cmos 26424 0
    rtc_core 33348 1 rtc_cmos
    rtc_lib 19776 1 rtc_core
    bnx2 186824 0
    pcspkr 19328 0
    ata_piix 36484 0
    libata 181504 1 ata_piix
    shpchp 45468 0
    mptsas 47696 7
    mptscsih 49472 1 mptsas
    mptbase 90020 2 mptsas,mptscsih
    scsi_transport_sas 47616 1 mptsas
    sd_mod 42984 11
    scsi_mod 172536 8 scsi_dh,sg,sr_mod,libata,mptsas,mptscsih,scsi_transport_sas,sd_mod
    ext3 136784 2
    jbd 62824 1 ext3
    uhci_hcd 37408 0
    ohci_hcd 38172 0
    ehci_hcd 47948 0
    [/bash]



  6. /proc 这个目录下有很多重要的信息。cd /procls,用 cat 读取该目录下的信息,如 cpuinfo, devices, filesystems, meminfo, partitions, swaps, uptime, version 等,也可进 proc 的子目录查看信息,如 cd driver
    [bash collapse="true"]
    [root@www ~]# cat /proc/cpuinfo
    processor : 0
    vendor_id : GenuineIntel
    cpu family : 6
    model : 26
    model name : Intel(R) Xeon(R) CPU E5502 @ 1.87GHz
    stepping : 5
    cpu MHz : 1861.992
    cache size : 4096 KB
    physical id : 1
    siblings : 2
    core id : 0
    cpu cores : 2
    apicid : 16
    initial apicid : 16
    fpu : yes
    fpu_exception : yes
    cpuid level : 11
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr dca sse4_1 sse4_2 popcnt lahf_lm
    bogomips : 3723.98
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management:

    processor : 1
    vendor_id : GenuineIntel
    cpu family : 6
    model : 26
    model name : Intel(R) Xeon(R) CPU E5502 @ 1.87GHz
    stepping : 5
    cpu MHz : 1861.992
    cache size : 4096 KB
    physical id : 0
    siblings : 2
    core id : 0
    cpu cores : 2
    apicid : 0
    initial apicid : 0
    fpu : yes
    fpu_exception : yes
    cpuid level : 11
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr dca sse4_1 sse4_2 popcnt lahf_lm
    bogomips : 3723.44
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management:

    processor : 2
    vendor_id : GenuineIntel
    cpu family : 6
    model : 26
    model name : Intel(R) Xeon(R) CPU E5502 @ 1.87GHz
    stepping : 5
    cpu MHz : 1861.992
    cache size : 4096 KB
    physical id : 1
    siblings : 2
    core id : 2
    cpu cores : 2
    apicid : 20
    initial apicid : 20
    fpu : yes
    fpu_exception : yes
    cpuid level : 11
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr dca sse4_1 sse4_2 popcnt lahf_lm
    bogomips : 3723.42
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management:

    processor : 3
    vendor_id : GenuineIntel
    cpu family : 6
    model : 26
    model name : Intel(R) Xeon(R) CPU E5502 @ 1.87GHz
    stepping : 5
    cpu MHz : 1861.992
    cache size : 4096 KB
    physical id : 0
    siblings : 2
    core id : 2
    cpu cores : 2
    apicid : 4
    initial apicid : 4
    fpu : yes
    fpu_exception : yes
    cpuid level : 11
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr dca sse4_1 sse4_2 popcnt lahf_lm
    bogomips : 3723.44
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management:

    [root@www ~]# cat /proc/version
    Linux version 2.6.27 (root@www) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-48)) #1 SMP Fri Oct 15 00:59:47 CST 2010
    [root@www ~]# cat /proc/swaps
    Filename Type Size Used Priority
    /dev/sda3 partition 4192956 212 -1
    [/bash]


  7. top 实时显示系统当前的进程和其他状况,详细到 这里
    [bash collapse="true"]
    [root@www ~]# top
    top - 16:36:08 up 217 days, 1:55, 1 user, load average: 0.00, 0.00, 0.00
    Tasks: 182 total, 1 running, 181 sleeping, 0 stopped, 0 zombie
    Cpu0 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
    Cpu1 : 0.0%us, 0.0%sy, 0.0%ni, 99.0%id, 1.0%wa, 0.0%hi, 0.0%si, 0.0%st
    Cpu2 : 0.0%us, 0.3%sy, 0.0%ni, 98.7%id, 1.0%wa, 0.0%hi, 0.0%si, 0.0%st
    Cpu3 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
    Mem: 8186612k total, 8021152k used, 165460k free, 201404k buffers
    Swap: 4192956k total, 212k used, 4192744k free, 6758848k cached

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    13373 root 20 0 1165m 82m 9924 S 0.3 1.0 17:58.03 java
    24688 root 20 0 2474m 665m 651m S 0.3 8.3 31344:13 mongod
    1 root 20 0 10356 640 536 S 0.0 0.0 1:06.25 init
    2 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kthreadd
    3 root RT -5 0 0 0 S 0.0 0.0 0:00.60 migration/0 4 root 15 -5 0 0 0 S 0.0 0.0 0:01.02 ksoftirqd/0 5 root RT -5 0 0 0 S 0.0 0.0 0:00.73 watchdog/0
    6 root RT -5 0 0 0 S 0.0 0.0 0:01.13 migration/1
    7 root 15 -5 0 0 0 S 0.0 0.0 0:00.77 ksoftirqd/1
    8 root RT -5 0 0 0 S 0.0 0.0 0:00.03 watchdog/1
    9 root RT -5 0 0 0 S 0.0 0.0 0:01.89 migration/2
    10 root 15 -5 0 0 0 S 0.0 0.0 0:00.57 ksoftirqd/2
    11 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/2
    12 root RT -5 0 0 0 S 0.0 0.0 0:02.08 migration/3
    13 root 15 -5 0 0 0 S 0.0 0.0 0:00.63 ksoftirqd/3
    14 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/3
    15 root 15 -5 0 0 0 S 0.0 0.0 4:57.46 events/0
    16 root 15 -5 0 0 0 S 0.0 0.0 3:36.12 events/1
    17 root 15 -5 0 0 0 S 0.0 0.0 3:52.82 events/2
    18 root 15 -5 0 0 0 S 0.0 0.0 3:43.96 events/3
    19 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 khelper
    141 root 15 -5 0 0 0 S 0.0 0.0 0:01.16 kblockd/0
    142 root 15 -5 0 0 0 S 0.0 0.0 0:00.43 kblockd/1
    143 root 15 -5 0 0 0 S 0.0 0.0 0:07.63 kblockd/2
    144 root 15 -5 0 0 0 S 0.0 0.0 0:00.56 kblockd/3
    146 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpid
    147 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kacpi_notify
    256 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 cqueue
    258 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 ksuspend_usbd
    264 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 khubd
    267 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kseriod
    340 root 15 -5 0 0 0 S 0.0 0.0 0:17.71 kswapd0
    341 root 15 -5 0 0 0 S 0.0 0.0 0:21.69 kswapd1
    342 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 aio/0
    343 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 aio/1
    344 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 aio/2
    345 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 aio/3
    [/bash]

  8. htoptop 更好,可查看进程间的交互。

  9. ctrl-es KDE 才有,按下后出现 Process Table。

  10. prcinfo 收集 /proc 下的信息并将之打印。

  11. 其它相关命令

    • ps aux

    • ps -e

    • swapon -s 显示 swap 的分区和信息
      [bash]
      [root@www ~]# swapon -s
      Filename Type Size Used Priority
      /dev/sda3 partition 4192956 212 -1
      [/bash]

    • swapon -a 自动启动所有 swap

    • /etc/fstab 包含文件系统的配置信息
      [bash collapse="true"]
      [root@www ~]# cat /etc/fstab
      LABEL=/ / ext3 defaults 1 1
      LABEL=/boot1 /boot ext3 defaults 1 2
      tmpfs /dev/shm tmpfs defaults 0 0
      devpts /dev/pts devpts gid=5,mode=620 0 0
      sysfs /sys sysfs defaults 0 0
      proc /proc proc defaults 0 0
      LABEL=SWAP-sda3 swap swap defaults 0 0
      /dev/sdb1 /data/dev10 xfs defaults 0 0
      /dev/sdc1 /data/dev11 xfs defaults 0 0
      /dev/sdd1 /data/dev12 xfs defaults 0 0
      /dev/sda4 /soft xfs defaults 0 0
      [/bash]

    • free 查看内存使用情况,详细 这里

    • KSysGuard 系统监视器,即 KDE 系统监视器,当中有包含内存的使用情况报告。

    • df -h , 以易读的方式显示目前磁盘空间和使用情况,详细 这里

    • du / -bh | more

    • du -s /var/log/*

    • hdparm -t /dev/sda 显示硬盘 sda 当前性能状况。
      [bash]
      [root@www ~]# hdparm -t /dev/sda

      /dev/sda:
      Timing buffered disk reads: 448 MB in 3.01 seconds = 148.74 MB/sec
      You have new mail in /var/spool/mail/root
      [/bash]

    • arch 显示 CPU 的标志,但这个可能错误,如果有安装 rpm,可用 rpm --showrc | grep " arch" 检测。
      [bash]
      [root@www ~]# arch
      x86_64
      [root@www ~]# rpm --showrc | grep " arch"
      build arch : x86_64
      compatible build archs: ia32e x86_64 noarch
      install arch : ia32e
      compatible archs : ia32e x86_64 athlon noarch amd64 i686 i586 i486 i386 fat
      [/bash]

    • ifconfig -a

    • date

    • uptime



  12. cat /proc/PID/staus 查看进程当前状态
    [bash collapse="true"]
    [root@www ~]# cat /proc/12452/status
    Name: gearmand
    State: S (sleeping)
    Tgid: 12452
    Pid: 12452
    PPid: 1
    TracerPid: 0
    Uid: 0 0 0 0
    Gid: 0 0 0 0
    FDSize: 64
    Groups: 0 1 2 3 4 6 10
    VmPeak: 407808 kB
    VmSize: 309188 kB
    VmLck: 0 kB
    VmHWM: 232476 kB
    VmRSS: 109976 kB
    VmData: 275676 kB
    VmStk: 84 kB
    VmExe: 284 kB
    VmLib: 4172 kB
    VmPTE: 404 kB
    Threads: 7
    SigQ: 1/71680
    SigPnd: 0000000000000000
    ShdPnd: 0000000000000000
    SigBlk: 0000000000000000
    SigIgn: 0000000000001000
    SigCgt: 0000000180004203
    CapInh: 0000000000000000
    CapPrm: fffffffffffffeff
    CapEff: fffffffffffffeff
    CapBnd: fffffffffffffeff
    voluntary_ctxt_switches: 48135
    nonvoluntary_ctxt_switches: 19085
    [/bash]



Bash Info



  1. echo $PATH 输出当前用户环境变量 PATH

  2. echo $? 输出最后一次调用的命令的退出码。

  3. help 列出所有 shell 内置的命名, help name 显示命令 name 的帮助信息。

  4. whereis 列出命令的二进制文件,源代码,以及帮助文件的位置。

  5. which

  6. type (name) 表明当 name 做为命令执行时的解析情况

  7. alias 列出所有的别名命令

  8. unalias 永久的删除所有别名命令,直到重新设置。

  9. "command" 命令用引号引起来,将会做为 true 命令调用 (如果存在的话),而不是其别名。

  10. file 显示文件类型
    [bash]
    [root@www tmp]# file test.php
    test.php: PHP script text
    [root@www tmp]# file -i test.php
    test.php: text/plain; charset=us-ascii
    [root@www tmp]# file -iz test.php
    test.php: text/plain; charset=us-ascii
    [root@www tmp]# file -s test.php
    test.php: PHP script text
    [/bash]

  11. tree
    [bash]
    [root@www test]# tree
    .
    |-- 1.php
    |-- 2.php
    `-- 3.php

    0 directories, 3 files
    [/bash]

  12. cal
    [bash collapse="true"]
    [root@www ~]# cal
    October 2012
    Su Mo Tu We Th Fr Sa
    1 2 3 4 5 6
    7 8 9 10 11 12 13
    14 15 16 17 18 19 20
    21 22 23 24 25 26 27
    28 29 30 31
    [root@www test]# cal -3
    September 2012 October 2012 November 2012
    Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
    1 1 2 3 4 5 6 1 2 3
    2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10
    9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17
    16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24
    23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30
    30
    [root@www test]# cal 10 2012
    October 2012
    Su Mo Tu We Th Fr Sa
    1 2 3 4 5 6
    7 8 9 10 11 12 13
    14 15 16 17 18 19 20
    21 22 23 24 25 26 27
    28 29 30 31

    [/bash]

Install systemtap

CentOS 5.3, Linux 2.6.6,64 位

下载 源代码 ,配置,报错:
[bash]
[root@www systemtap-2.0]# ./configure --prefix=/usr/local/systemtap
......
configure: error: missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)
[/bash]

据错误提示,用 yum 安装依赖:
[bash]
[root@www systemtap-2.0]# yum install elfutils.x86_64 -y
[root@www systemtap-2.0]# yum install elfutils-devel.x86_64 -y
[/bash]

配置 systemtap,提示:
[bash]
[root@www systemtap-2.0]# ./configure --prefix=/usr/local/systemtap
......
configure: error: elfutils, libdw too old, need 0.148+
[/bash]

Googling elfutils, libdw,基本都是 rpm 包,于是换成用 rpm 包来安装,从 这里 下载 systemtapkernel-develsystemtap-runtime 这三个 rpm 包,system-runtime 和 kernel-devel 包是 systemtap 的依赖包。

[bash]
[root@www src]# rpm -Uhv systemtap-1.6-7.el5_8.x86_64.rpm systemtap-runtime-1.6-7.el5_8.x86_64.rpm kernel-devel-2.6.18-308.el5.x86_64.rpm
Preparing... ########################################### [100%]
package kernel-devel-2.6.18-308.el5.x86_64 is already installed
package systemtap-runtime-1.6-7.el5_8.x86_64 is already installed
package systemtap-1.6-7.el5_8.x86_64 is already installed
# 检查安装是否成功。如果部署成功,运行下面命令,输出应该类似于如下:
[root@www src]# stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'
Pass 1: parsed user script and 76 library script(s) using 147620virt/22500res/2996shr kb, in 190usr/20sys/240real ms.
Pass 2: analyzed script: 1 probe(s), 22 function(s), 3 embed(s), 1 global(s) using 277912virt/85372res/5892shr kb, in 1140usr/90sys/2714real ms.
Pass 3: translated to C into "/tmp/stapXXnotG/stap_59817f232930c1e1240b1253994e85c9_10707_src.c" using 272140virt/84864res/6580shr kb, in 380usr/20sys/409real ms.
Pass 4: compiled C into "stap_59817f232930c1e1240b1253994e85c9_10707.ko" in 2060usr/290sys/3607real ms.
Pass 5: starting run.
read performed
Pass 5: run completed in 10usr/20sys/557real ms.
[/bash]

Resourcess:

2012年10月29日星期一

进程运行于不同的 CPU 核

用 Gearman 搭建 Map/Reduce ,GearmanManager 来管理所有的 workers。启动多个 gearman-manager daemon,为了充分利用服务器资源,使其运行于不同的 CPU 内核上。 假设启动 10 个gearman-manager daemon,CPU 是 4核。
[root@www ~]# ps aux | grep gearman-manager | awk {'print $2;'} | sort -k1,1 | head -3 | xargs -n 1 taskset -cp 0
[root@www ~]# ps aux | grep gearman-manager | awk {'print $2;'} | sort -k1,1 | tail -3 | xargs -n 1 taskset -cp 1
[root@www ~]# ps aux | grep gearman-manager | awk {'print $2;'} | sort -k1,1 | sed -n '4,7p' | xargs -n 1 taskset -cp 2
上面命令是将前 3 个 deamon 运行于 CPU#0 (CPU 第一个核 上,从 0 开始计数),中间 4个运行于 CPU#2,最后三个运行于 CPU#1。 Backgrounds: 榨干服务器:让进程运行在指定的CPU
两个名词: SMP (Symmetrical Multi-Processing):指在一个计算机上汇集了一组处理器(多 CPU),各 CPU 之间共享内存子系统以及总线结构。 [MORE...] CPU affinity:中文唤作「CPU亲和力」,是指在 CMP 架构下,能够将一个或多个进程绑定到一个或多个处理器上运行。[MORE...]
  1. 在Linux上修改进程的「CPU亲和力」在Linux上,可以通过 taskset 命令进行修改。以 CentOS 为 例,taskset 在 util-linux-2.13-pre7 包中。下载源代码,编译安装即可。 对运行中的进程,可用如下命令将 CPU #1, #2, #3 分配给 PID 为 12345 的进程:
    [root@www ~]# taskset -cp 1,2,3 12345
    
    对于已经在运行中 MySQL 的服务,用上面命令修改其运行于哪颗 CPU 内核上是无效的。而是需要在启动时指定:
    [root@www ~]# taskset -c 1,2,3 /usr/local/mysql/bin/mysqld_safe &
    
    其它进程,也可类似处理 (Nginx 除外,见下文)。之后用 top 命令,回车后输入 1 查看所有 CPU 的使用情况:
  2. Nginx 绑定 CPU 上文说 Nginx 除外,是因为 Nginx 提供了更确切的配置,在其配置文件 conf/nginx.conf 中,有如下一行:
    worker_processes 1;  
    
    这用来配置 Nginx 启动几个工作进程,默认为 1。Nginx 还支持 worker_cpu_affinity 配置项,即 Nginx 可以为 每个工作进程绑定 CPU。例:
    worker_process      3;
    worker_cpu_affinity 0010 0100 1000;
    
    001001001000是掩码,分别代表第 2,3,4 颗 CPU 核。重启 Nginx,3 个工作进程就可以各自用各自的 CPU 。
  3. 深入
    • 如果自己写代码,要把进程绑定到 CPU,可用 sched_setaffinity 函数,在 Linux上,这会触发一次 系统调用
    • 如果父进程设置了affinity,之后其创建的子进程会继承父进程的affinity属性(其实用 taskset 启动进程就是一次fork+exec)。
  4. @Xitong Linode 默认只在 CPU#0 上工作,多半是由 Xen 的配置决定的。只要内核支持 SMP,默认都是尽可能将负载分摊在多个 CPU 上。

Some Notes


  1. ulimit -t 引起的kill血案

  2. 本机Linux下IO测试过程记录

  3. @hellodba :iostat中的 %util 代表一秒内 IO 操作所占的比例,计算公式是 (r/s+w/s)*(svctm/1000),对于一块磁盘,因为没有并发 IO 的概念,所以这个公式是正确的,但是对于 RAID 磁盘组或者 SSD 来说,这个计算公式就有问题了,就算这个值超过 100%,也不代表存储有瓶颈,容易产生误导。


    • @何_登成:#数据库内核分享# TPS1: InnoDB/Oracle 在数据文件头中记录有 Flush_LSN/Media Recovery CP SCN,二者均是用来标识当前数据文件对应的日志文件位置,但是维护与功能上有极大地不同。维护上:InnoDB Flush LSN 仅仅在 MySQL 数据库正常关闭时才更新;Oracle 的 MR SCN 是在日志文件切换后逐步更新。

    • @何_登成: 想到一个让 InnoDB 也支持 Media Recovery Checkpoint 的方案,让 InnoDB 在日志文件切换后,进行 MRC,并将新日志文件的 First LSN 作为 Flush LSN 写入每个 Data Files 的第一个 Page 中。如此做的优势,任何时候直接 Copy InnoDB 的数据文件,均可找到 Redo 的恢复起点。


  4. @stvchu :存储相关(数据库,文件存储)的工程师必须知道的 3 个计算公式。。。特别是第三个。。。知道为什么一般 I/O 利用率要保持在 60%~70% 以下了吧。。。PS: 图中红色数字参考希捷 300G SAS 15KRPM 的规格。



    • @hellodba:昨天团队又出现个 case,MySQL 复制一切正常,但是实际数据并没有复制过去,IO 和 SQL 线程都正常,relaylog 也有,原因还在进一步查。幸好发现了,如果主备切换就惨了,另外监控也要加强,不能只看状态,还要检测心跳的时间才行。

    • @hellodba:解析 binlog 发现主库 tableid 发生变化,备库复制时被忽略掉,原因不明,坑爹啊。

    • @AlibabaDBA:实际案例:MySQL 空表加字段,因为 BP(Buffer Pool) 比较大,Innodb 会多次遍历 BP 作清理,导致每个操作需要 1s,期间持有 LOCK_open 全局锁,造成其他查询均等待 Opening tables,实际操作中连续作了 64 个 DDL,造成整个系统 hang 了接近 1 分钟。结论:MySQL作大量 create, alter, drop操作必须 sleep。分析人:@希羽hickey

    • @hellodba:原因在此,宝贵经验。


  5. Ext4 data corruption trouble

  6. SystemTap,Linux 内核诊断工具,提供从运行中的 Linux 内核获取信息。

  7. Google Data Center

  8. Line,简短介绍,相当于微信,但比微信强大。

MongoDB: Why "Uncaught exception 'MongoConnectionException... endpoint not connected"

在 PHP 中访问 MongoDB,建立连接时收到异常:
[bash gutter="fasle"]
"Uncaught exception 'MongoConnectionException transport endpoint is not connected"
[/bash]

Mongo Exception 中有说明引发这异常的原因:

Transport endpoint is not connected
Generally means that the connection string isn't correct, the driver couldn't even find the database server.


具体就是指定义提供服务的 server 的格式不对,正常的格式是: mongodb://[username:password@]host1[:port1][,host2[:port2:],...]/db

CPAN02packagesDetails包错误导致cpan不能用



新主机上用 cpan 安装失败,用上面方法未解决。于是,删除 $HOME/.cpan,然后从其它可用的主机上 copy 了一份,重新加载 (reload index),报源 404 错误。从 CPAN 不可用 文中看到这段:

再次尝试安装模块,系统按照顺序尝试各个源,两个404之后(就是那两个碰不到的源),ftp://cpan.cdpa.nsysu.edu.tw/Unix/Lang/CPAN/里找到了我们需要的package信息,不过因为已经有了,所以需要手动先删除 /root/.cpan/sources/modules/02packages.details.txt.gz 和 /root/.cpan/sources/modules/03modlist.data.gz,再重新install CGI,一切正常了。不过老看到两个404也很不爽,就干脆手动编辑配置文件/usr/lib/perl5/5.8.8/CPAN/Config.pm,把"'urllist' =>" 中的两个不能访问的源干掉,一切都好了,以下是修改后的配置文件

试着修改 /usr/lib/perl5/5.8.8/CPAN/Config.pmurllist,将报 404 的源删除。安装,成功。

这里,不知道是不是因为 404 错误的源在 urllist 最前面,以至报整个安装失败,还是有别的因素导致失败。总之,后面这无礼而又粗暴的方法算暂时解决了问题。

编译 PHP 时报 undefined reference to `libiconv_open'

编译 PHP 5.4.7,配置参数:
[bash]
./configure --prefix=/usr/local/php --with-freetype-dir --with-jpeg-dir --with-png-dir --with-curl --with-gd --with-iconv --with-mcrypt --with-mhash --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-openssl --with-pdo-mysql=mysqlnd --with-gettext --with-zlib --enable-bcmath --enable-ftp --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-gd-native-ttf --enable-mbstring --enable-pcntl --enable-pdo --enable-sockets --enable-shmop --enable-zip --disable-ipv6 --disable-debug --without-pear
[/bash]
configure 正常,make 时报错:
[bash]
ext/gd/libgd/gdkanji.o: In function `do_convert':
/usr/local/src/php-5.4.7/ext/gd/libgd/gdkanji.c:350: undefined reference to `libiconv_open'
/usr/local/src/php-5.4.7/ext/gd/libgd/gdkanji.c:365: undefined reference to `libiconv'
/usr/local/src/php-5.4.7/ext/gd/libgd/gdkanji.c:381: undefined reference to `libiconv_close'
ext/iconv/iconv.o: In function `_php_iconv_strlen':
.....
collect2: ld returned 1 exit status
make: *** [sapi/cli/php] Error 1
[/bash]

看错误提示,gd 库调用 libiconv, 但没找到 libiconv。下载 libiconv,编译,安装。

再重新配置 PHP ,加上 --with-iconv=/usr/local/lib
[bash]
[root@www php-5.4.7]# ./configure --prefix=/usr/local/php --with-freetype-dir --with-jpeg-dir --with-png-dir --with-curl --with-gd --with-iconv --with-mcrypt --with-mhash --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-openssl --with-pdo-mysql=mysqlnd --with-gettext --with-zlib --enable-bcmath --enable-ftp --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-gd-native-ttf --enable-mbstring --enable-pcntl --enable-pdo --enable-sockets --enable-shmop --enable-zip --disable-ipv6 --disable-debug --without-pear
[root@www php-5.4.7]# make
[root@www php-5.4.7]# make install
[/bash]

PHP Notes

exec()


  1. 获得命令执行结果,命令和参数完后加上 2>&1
    [bash]
    $output = array();
    $lastLine = exec("php -l test.php 2>&1", $output);
    [/bash]

  2. 立即退出,而不是等命令执行完后再退出
    [bash]
    exec("php -l test.php > /dev/null &");
    [/bash]



php_sapi_name()

返回 小写的 PHP 使用的 interface。如从命令行执行时返回 cli


Deprecated: Assigning the return value of new by reference is deprecated in ...

运行旧时代码,收到错误:
[php gutter="false"]
Deprecated: Assigning the return value of new by reference is deprecated in .. line
[/php]
Google ,原来是 PHP 升级引发的问题。PHP 从 5.3 起,废除了 =& 符号,用 = 就等于是直接引用。详细如下:

  1. PHP5 对象复制是采用引用的方式

  2. 如果不采用引用方式,则需要在复制对象时加关键字 clone

  3. 如果在复制的过程中,同时要变更某些属性,则增加函数 _clone()



Problem: Fatal error: Call to undefined function: pcntl_fork() in ...

编译 PHP 有加上参数 --enable-pcntl,且安装成功后,在 PHP 信息中,能看到 PHP 支持 pcntl 的信息:
[bash]
[root@www ~]# php -i | grep pcntl
Configure Command => './configure' '--prefix=/usr/local/php' '--with-freetype-dir' '--with-jpeg-dir' '--with-png-dir' '--with-curl' '--with-gd' '--with-iconv' '--with-mcrypt' '--with-mhash' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-openssl' '--with-pdo-mysql=mysqlnd' '--with-gettext' '--with-zlib' '--enable-bcmath' '--enable-ftp' '--enable-fpm' '--with-fpm-user=www' '--with-fpm-group=www' '--enable-gd-native-ttf' '--enable-mbstring' '--enable-pcntl' '--enable-pdo' '--enable-sockets' '--enable-sqlite-utf8' '--enable-shmop' '--enable-zip' '--disable-ipv6' '--disable-debug' '--without-pear'
pcntl
pcntl support => enabled
[/bash]

在浏览器中访问有调用 pcntl_fork()的脚本时,收到下面的错误提示,但在命令行执行该脚本时正常运行:
[bash]
Problem: Fatal error: Call to undefined function: pcntl_fork() in ...
[/bash]

PHP 官方网站在 介绍 pcntl 时有提到:
Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.

即调用 pcntl_xxx 系列函数的脚本,不能在浏览器或是任何 web 方式的环境下访问。


Strict Standards: Only variables should be passed by reference

[php]
<?php
$string = 'test1 test2 test3 test4';
$array = array_shift(explode(' ', $string));

print_r($array);
?>
[/php]
执行上面代码,收到错误:
[bash gutter="false"]
[root@www tmp]# php test.php
PHP Strict Standards: Only variables should be passed by reference in /tmp/test.php on line 3

Strict Standards: Only variables should be passed by reference in /tmp/test.php on line 3
[/bash]
之所以报这错误,因为 array_shift 的参数是引用传递的,PHP 5.3+ 默认只能传递具体的变量,而不能直接是传递函数返回值。代码修改成:
[php]
<?php
$string = 'test1 test2 test3 test4';
$array = explode(' ', $string);
$value1 = array_shift($array);

print_r($value1);
?>
[/php]
另外,当程序设置的报错模式为严格模式时也会收到上面的错误:
[php]
error_reporting (E_ALL | E_STRICT);
[/php]

Resources:

Gearman 1.1.0 + PECL Gearman PHP 1.03 - compilation problem

Gearman 1.1.0 安装成功,安装扩展 PECL Gearman PHP 1.0.3, 编译失败:
[bash]
[root@www gearman-1.0.3]# make
/bin/sh /usr/local/src/gearman-1.0.3/libtool --mode=compile cc -I. -I/apps/home/folder/local/folder4/gearman-1.0.3 -DPHP_ATOM_INC -I/usr/local/src/gearman-1.0.3/include -I/usr/local/src/gearman-1.0.3/main -I/apps/home/folder/local/folder4/gearman-1.0.3 -I/usr/local/php/include/php -I/usr/local/php/include/php/main -I/usr/local/php/include/php/TSRM -I/usr/local/php/include/php/Zend -I/usr/local/php/include/php/ext -I/usr/local/php/include/php/ext/date/lib -I/usr/local/php/include -DHAVE_CONFIG_H -g -O2 -Wall -c /usr/local/src/gearman-1.0.3/php_gearman.c -o php_gearman.lo
cc -I. -I/apps/home/folder/local/folder4/gearman-1.0.3 -DPHP_ATOM_INC -I/usr/local/src/gearman-1.0.3/include -I/usr/local/src/gearman-1.0.3/main -I/apps/home/folder/local/folder4/gearman-1.0.3 -I/usr/local/php/include/php -I/usr/local/php/include/php/main -I/usr/local/php/include/php/TSRM -I/usr/local/php/include/php/Zend -I/usr/local/php/include/php/ext -I/usr/local/php/include/php/ext/date/lib -I/usr/local/php/include -DHAVE_CONFIG_H -g -O2 -Wall -c /usr/local/src/gearman-1.0.3/php_gearman.c -fPIC -DPIC -o .libs/php_gearman.o
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_data’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1486: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_warning’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1514: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_status’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1537: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_complete’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1559: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_exception’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1581: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zif_gearman_job_send_fail’:
/usr/local/src/gearman-1.0.3/php_gearman.c:1600: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘_php_worker_function_callback’:
/usr/local/src/gearman-1.0.3/php_gearman.c:3521: error: dereferencing pointer to incomplete type
/usr/local/src/gearman-1.0.3/php_gearman.c: In function ‘zm_startup_gearman’:
/usr/local/src/gearman-1.0.3/php_gearman.c:4638: error: ‘GEARMAN_MAGIC_TEXT’ undeclared (first use in this function)
/usr/local/src/gearman-1.0.3/php_gearman.c:4638: error: (Each undeclared identifier is reported only once
/usr/local/src/gearman-1.0.3/php_gearman.c:4638: error: for each function it appears in.)
/usr/local/src/gearman-1.0.3/php_gearman.c:4641: error: ‘GEARMAN_MAGIC_REQUEST’ undeclared (first use in this function)
/usr/local/src/gearman-1.0.3/php_gearman.c:4644: error: ‘GEARMAN_MAGIC_RESPONSE’ undeclared (first use in this function)
make: *** [php_gearman.lo] Error 1
......
[/bash]

bugs.php.net 有列出该问题 Bug #63062 gearman extension compile error,从评论中可得知,该问题在 Gearman 上也有对应 gearman_worker_st no longer visible from gearman_job_st,下面有说明在 gearmand-1.1.1 中该问题已被 fix。

Herman J. Radtke III (hermanradtke) wrote on 2012-09-20: #8
I was able to successfully compile against the gearmand-1.1.1 release.

Brian Aker (brianaker) on 2012-09-20
Changed in gearmand:
status: Fix Committed → Fix Released

GearmanMonitor 和 GearmanManager

GearmanMonitor

GearmanMonitor 是用来查看 Gearman 服务状态的工具,包括 运行中/过的队列 Queue,运行中的所有 workers,及服务器 servers。GearmanMonitor 需要有 Net_Gearman 支持。安装 pear 后,直接执行:
[bash]
[root@www bin]# pear install Net_Gearman
# 如果提示
# No releases available for package "pear.php.net/Net_Gearman"
# 则执行
[root@www bin]# pear install channel://pear.php.net/Net_Gearman-0.2.3
[/bash]

GearmanManager

GearmanManager 用来统一管理用 PHP 编写的 Gearman workers。需要 PHP 启用 pcntl。用 install/install.sh 安装完成后,根据需要和设置,修改 /etc/init.d/gearman-manager:
[bash gutter="false"]
##PATH##
DAEMON=/usr/local/bin/gearman-manager
PIDDIR=/tmp
PIDFILE=${PIDDIR}/manager.pid
LOGFILE=/tmp/gearman-manager.log
CONFIGDIR=/data/gearman-manager
GEARMANUSER="gearmand"
PARAMS="-c ${CONFIGDIR}/config.ini"
[/bash]

GearmanManager 安装时,选择的是 PECL library,启动时可能会遇见如下的问题:
[bash]
[root@www gearman-manager]# /etc/init.d/gearman-manager start
Starting gearman-manager: [ OK ]
[root@www gearman-manager]# php: libgearman/universal.cc:553: bool gearman_request_option(gearman_universal_st&, gearman_string_t&): Assertion `con->recv_state == GEARMAN_CON_RECV_UNIVERSAL_NONE' failed.
php: libgearman/universal.cc:553: bool gearman_request_option(gearman_universal_st&, gearman_string_t&): Assertion `con->recv_state == GEARMAN_CON_RECV_UNIVERSAL_NONE' failed.
.....
[/bash]

解决办法如 Bug #60764 Enabling Non-Blocking Mode causes asseration 这里所提, 修改 pecl-manager.php :
[bash]
//注释下面这句
//$thisWorker->addOptions(GEARMAN_WORKER_NON_BLOCKING);
[/bash]

Temporary failure in name resolution

用 wget 下载资源,出现
[bash gutter="false"]
[root@ src]# wget http://cdn.mysql.com/Downloads/MySQL-5.5/mysql-5.5.28.tar.gz
Resolving http://cdn.mysql.com/Downloads/MySQL-5.5/mysql-5.5.28.tar.gz failed: Temporary failure in name resolution.
[/bash]
错误提示表示在解析 URL 时候失败。
检测机器的网络问题: 可 ping 外部 IP 地址, 但 ping 外部 URL 时, 提示 the host is unknown
修改 /etc/resolv.conf DNS 设置文件, service network restart 重启网络服务。问题解决。


用命令 yum 安装软件时,收到类似如下的错误提示:
[bash gutter="false"]
[root@www ~]# yum install boost.x86_64
Could not retrieve mirrorlist [url]http://mirrorlist.centos.org/?release=5&arch=i386&repo=os[/url] error was
[Errno 4] IOError: <urlopen error (-3, '\xe5\x9f\x9f\xe5\x90\x8d\xe8\xa7\xa3\xe6\x9e\x90\xe6\x9a\x82\xe6\x97\xb6\xe5\xa4\xb1\xe8\xb4\xa5')>
Error: Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again
[/bash]
这也是 DNS 设置的问题。

Hadoop 常用命令


  1. hadoop namenode -format
    HDFS 格式化

  2. hadoop fs -rmr wordoutput
    删除 HDFS 中 wordcount 目录

  3. hadoop fs -put word-input/ wordinput
    将本地文件系统中 word-input 上传到 HDFS 中,对应目录名为 wordinput

  4. hadoop dfs -copyFromLocal /tmp/gutenberg /user/hduser/gutenberg
    将本地文件系统上的文件 /tmp/gutenberg 复制到 Hadoop 的 HDFS /user/hduser/gutenberg 中

  5. hadoop dfs -getmerge /user/hduser/gutenberg-output /tmp/gutenberg-output
    将 HDFS 中文件 /user/hduser/gutenberg-output 复制到 本地文件系统的 /tmp/gutenberg-output

  6. hadoop dfs -ls /user/hduser/wordinput
    列出 HDFS 中 /user/hduser/wordinput 目录/文件 的信息

  7. hadoop dfs -cat /user/hduser/gutenberg-output/part-r-00000
    查看 HDFS 中文件 /user/hduser/gutenberg-output/part-r-00000

  8. hadoop jar hadoop-examples-1.0.3.jar wordcount wordinput wordoutput
    运行 wordcount JOB, wordinput 为数据处理源,wordoutput 存储 JOB 处理结果,wordinput 和 wordoutput 都为 HDFS 中目录。

  9. hadoop jar contrib/streaming/hadoop-streaming-1.0.3.jar -file /usr/local/hadoop/python/mapper.py -mapper /usr/local/hadoop-/python/mapper.py -file /usr/local/hadoop/python/reducer.py -reducer /usr/local/hadoop/python/reducer.py -input /user/hduser/wordinput -output /user/hduser/wordinput-python
    利用 Hadoop Streaming,使用 Python 脚本做为 mapper/reducer,JOB 处理的源数据为/user/hduser/wordinput, 输出结果保存于/user/hduser/wordinput-python。

  10. hadoop fsck /user
    检查 HDFS 中 /user 目录下 Blocks 的完整性

  11. hadoop fsck --delete
    删除损坏的文件

  12. hadoop balancer -threshold 5
    对 Hadoop 集群中对各个 Datanode 进行评估并使他们保持平衡。参数 threshold 表示的平衡的阀值,取值范围在 0% 到 100% 之间。该参数表示每个 Datanode 中空间使用率与 HDFS 集群总的空间使用率的差距百分比。


Linux 系统 NFS 服务端配置方法

FROM: NFS 伺服器
NFS(Network FileSystem)藉由网络共享文件系统的架设比较简单,最大的问题在于「权限」方面的概念。因为用户与服务器可能必须要具备相同的帐号才能读写某些目录或文件。另外,NFS 的启动需要使用远程过程调用协议(RPC)。也就是说,在使用 NFS 服务时,必须启动 RPC 服务。

修改 /etc/exports,增加共享目录


[bash]
[root@www ~]# vim /etc/exports
/tmp 192.168.100.0/24(ro) localhost(rw) *.edu.net(ro,sync)
#[共享目录] [第一部主机(权限)] [可用主机名] [可用域名]
/home/linux *.centos.vbird(rw,all_squash,anonuid=45,anongid=45)
# 如果要开发匿名,那重点是 all_squash,并且要配合 anonuid, anongid
[/bash]
上面说明:将 /tmp 分別共享给三个不同的主机或域。主机后面以小括号 () 括起来的部分表示权限参数,若权限参数不止一个,则以逗号 , 分开。小括号与主机名之间不能有空格。# 开头表示该行已被注释。

主机名称的设定方式:

  • 使用完整的 IP 或 网段,如: 192.168.100.10192.168.100.0/24, 或 192.168.100.0/255.255.255.0

  • 使用主机名称,但主机名称必须在 /etc/hosts 内,或可使用 DNS 找到该名称。如果是主机名称,支持匹配符号 *?



权限常见参数(小括号内参数):

























参数值 说明
rw
ro
目录功效的权限是可读写(read-write)或只读(read-only),但最终能不能读写,还与文件系统的 rwx 及其属主有关。
sync
async
sync 表示数据会同步写入到内存和硬盘中,async 表示数据会先暂存于内存中,而不后再写入到硬盘中。
no_root_squash
root_squash
挂载端若使用 NFS 文件系统的帐号为 root ,默认情况下,root 的身份会由 root_squach 的设置成为 nfsnobody,这种对服务器会比较有保障。但如果想要开放挂载端使用 root 身份来操作服务器的文件系统,那这里就需设置成 no_root_squach。
all_squash 不论使用 NFS 的 身份为何,都会被设置为匿名使用者,即 noboby(nfsnobody)。
anonuid
anongid
anon 意指 anonymous(匿名者),前面关于 *_squash 提到的匿名使用的 UID 设定值,通常为 nobody(nfsbody),但可以自行设定这个 UID 的值,当然,这个 UID 必需要存在于 /etc/passwd 当中。anonuid指 UID, 而 anongid指 GID。

启动与停止 NFS 服务


上面已提到,NFS 启动需要 rpcbind 的协助。
[bash gutter="false"]
[root@www ~]# /etc/init.d/rpcbind start
# 如果 rpcbind 本來就已經在运行,就不需要重新启动

[root@www ~]# /etc/init.d/nfs start
# 有时候某些 distributions 可能会出现如下的警告讯息:
exportfs: /etc/exports [3]: No 'sync' or 'async' option specified
for export "192.168.100.10:/home/test".
Assuming default behaviour ('sync').
# 上面的警告信息是在告知没有指定 sync 或 async 参数,NFS 默认会使用 sync,该警告可不理。

[root@www ~]# /etc/init.d/nfslock start
[root@www ~]# chkconfig rpcbind on
[root@www ~]# chkconfig nfs on
[root@www ~]# chkconfig nfslock on
[/bash]
若修改 /etc/exports 文件增加新的共享,应先停止 NFS 服务,再启动 NFS 服务方能使新增的共享起作用。使用命令 exportfs -rv也可达到同样的效果。

Linux 挂载其它 Linux 的 NFS 共享


[bash]
[root@www ~]# mkdir /mnt/nfs
# 建一个目录用作挂载点
[root@www ~]# mount -t nfs -o rw 192.168.100.1:/tmp /mnt/nfs
# 192.168.100.1 表示 NFS 服务端的主机 IP 地址,也可使用主机名,但需在 /etc/hosts 文件中。/tmp 是服务端共享的目录。
[root@www ~]# umount -f /mnt/nfs
#取消挂载
[/bash]

Using WGET with HTTP GET Parameters

FROM: Using WGET with HTTP GET Parameters

wget 在 *nix 系统中是一非常有用的工具,一般已由系统默认安装。

wget 可用来下载资源,如:
[bash]
wget http://cdn.mysql.com/Downloads/MySQL-5.5/mysql-5.5.28.tar.gz
[/bash]

附带参数:
[bash]
wget https://www.google.com/search?q=mysql
[/bash]
但当参数个数 >= 2 时,如果不将访问的链接用引号括起来,shell 会认为链接在 & 后就已经结束,请求解析失败。正确请求应是:
[bash]
wget "https://www.google.com/search?q=mysql&hl=en"
[/bash]

MySQL server has gone away

PHP 5.3.8,PDO 扩展在 PHP 源代码安装时启用。MySQL 5.1.4, Linux 2.6.27。

脚本伪代码:
[php]
$flags = array(
PDO::ATTR_PERSISTENT => true,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
$db = init_db($flags);

while(true) {
// retrieve data from db
}
[/php]

脚本运行时间超过 MySQL 服务器中设置的 wait_timeout 时间后,收到错误:
[sql gutter="false"]
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
[/sql]

修改脚本,初始化 DB 连接时,设置 PDO::ATTR_PERSISTENT = false,问题不再出现。


在 PHP 的 bug 列表中找到类似的问题
Bug #37319 "MySQL server has gone away", with PDO::ATTR_PERSISTENT => true
,从下面评论来看,似乎对于 PDO::ATTR_PERSISTENT = true 出现的问题还是没解决。

2012年9月29日星期六

Error: 2002 - No such file or directory

MySQL 5.1.4 ,PHP 5.3
[php]
$conn = mysql_connect('localhost', 'USER', 'PASSWORD');
if(!$conn) {
echo 'Error: ' . mysql_errno() . ' - ' . mysql_error();
}
[/php]

执行脚本得到错误:
[bash gutter="fasle"]
Error: 2002 - No such file or directory
[/bash]

打开 PHP 配置文件 php.ini,找到 mysql.default_socket
[bash]
mysql.default_socket=/path/to/mysql.sock
[/bash]

保存,重启 PHP 服务。

ERROR 1006 (HY000): Can't create database 'example' (errno: 28)

MySQL 5.1.4 ,系统 Linux 2.6.27


  • 检查 datadirtmpdir目录,用户mysql是否有写权限。

  • 检查 datadirtmpdir目录,空间是否已满。

ERROR 2003 (HY000): Can’t connect to MySQL server on (10061)

MySQL 5.1.4 ,系统 Linux 2.6.27,phpMyAdmin 3

因为是测试机器,源码安装 MySQL 后,图简便,直接复制之前的一 MySQL 配置文件。启动服务, phpMyAdmin 始终无法连接,收到错误
[bash gutter="false"]
ERROR 2003 (HY000): Can’t connect to MySQL server on (10061)
[/bash]
担心是因为 Cookie 问题,用不同主机的 MySQL Client 测试连接,收到同样的错误,检查权限设置,无问题。再看 MySQL 的配置文件,看到了坑爹的
[sql gutter="false"]
[mysqld]
skip-networking
[/sql]
skip-networking 启用后,MySQL 服务器关闭MySQL的TCP/IP连接方式,只提供采用 socket 方式的连接。配置文件原来是单机运行的 MySQL 配置。

Backgrounds:
[sql]
[mysqld]
skip-networking
bind-address = 127.0.0.1
[/sql]
与此相关的设置,还有 bind-address,设定该值后,MySQL Server 只接受来自该指定 IP 的连接。

问题已不是第一次遇见, 但是在检查权限,服务等等一番折腾后,才想起服务器中的配置是不是有限制。总认为,只要问题有见过,即使不是全部能记起,至少也应该会有印象。如此,还真是一讽刺。

2012年9月26日星期三

/usr/bin/env: php: No such file or directory

[php title="test-command.php"]
/usr/bin/env php
<?php
echo phpinfo();
?>
[/php]

[bash]
[root@www www]# ln -fs /usr/bin/test-command /tmp/test-command.php
[/bash]


[php title="test.php"]
<?php
exec('test-command');
?>
[/php]

在浏览器中访问 test.php,收到错误提示:
[bash]
/usr/bin/env: php: No such file or directory
[/bash]

这种情况下,除了要将 PHP 的执行目录(/usr/local/php/bin) 加入环境变量 $PATH,还需:
[bash]
[root@www www]# ln -fs /usr/bin/php /usr/local/php/bin/php
[/bash]

因为从安全考虑,不管对环境变量 $PATH 做什么设置,从浏览器访问时 $PATH 值都是 /usr/bin;/usr/local/bin

2012年8月29日星期三

MySQL MongoDB SQL 对应

FROM: SQL to Mongo Mapping Chart

































































































































































  SQL statement Mongo statement
DDL CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, a INT, b INT, age INT, name CHAR(32)) implicit; can also be done explicitly with
db.createCollection("user1")
ALTER TABLE users ADD ... implicit
DROP TABLE users db.users.drop()
CREATE DATABSE db_name implicite
SHOW DATABASES show dbs
USE db_name use db_name
SHOW TABLES show collections
CREATE INDEX idx_name ON users(name) db.users.ensureIndex({name : 1})
CREATE INDEX idx_name_ts ON users(name, ts DESC) db.users.ensureIndex({name : 1, ts : -1})
DROP INDEX idx_name ON users db.users.dropIndex({name : 1, ts : -1})
SHOW INDEXES FROM users db.users.getIndexes()
DML INSERT INTO users VALUES(3, 5) db.users.insert({a: 3, b: 5})
SELECT a, b FROM users db.users.find({}, {a : 1, b: 1})
SELECT * FROM users db.users.find()
SELECT * FROM users WHERE age = 33 db.users.find({age : 33})
SELECT a, b FROM users WHERE age = 33 db.users.find({age : 33}, {a : 1, b : 1})
SELECT * FROM users WHERE age = 33 ORDER BY name ASC db.users.find({age : 33}).sort({name : 1})
SELECT * FROM users ORDER BY name DESC db.users.find().sort({name : -1})
SELECT * FROM users WHERE age > 33 db.users.find({age : {$gt : 33}})
SELECT * FROM users WHERE age != 33 db.users.find({age : {$ne : 33}})
SELECT * FROM users WHERE age > 33 AND age <= 44 db.users.find({age : {$gt: 33, $lte : 44}})
SELECT * FROM users WHERE name LIKE "%Joe%" db.users.find({name : /Joe/})
SELECT * FROM users WHERE id IN (3, 4, 5) db.users.find({id, {$in : [3, 4, 5]}})
SELECT * FROM users WHERE id NOT IN (3, 4, 5) db.users.find({id, {$nin : [3, 4, 5]}})
SELECT * FROM users WHERE id = 2 db.users.find({id , {$all : [2]}})
SELECT * FROM users WHERE a = 1 AND name = 'Joe' db.users.find({ a : 1, name : 'Joe'})
SELECT * FROM users WHERE a = 1 OR b = 2 db.users.find({$or : [{a : 1}, {b : 2}]})
SELECT * FROM users WHERE name LIKE "Joe%" db.users.find({name : /^Joe/})
SELECT * FROM users WHERE name LIKE "%Joe" db.users.find({name : /Joe$/})
SELECT * FROM users LIMIT 20, 10 db.users.find().limit(10).skip(20)
SELECT * FROM users LIMIT 1 db.users.findOne()
SELECT id FROM users u , users_extend e WHERE u.user_id = e.user_id AND e.c = 12345 db.users.find({"users_extend.c" : 12345}, {_id : 1})
SELECT customer.name FROM customers, orders WHERE orders.id = "q139" AND orders.custid = customers.id var o = db.orders.findOne({_id : "q139"})
var name = db.customers.findOne({_id : o.custid})
EXPLAIN SELECT * FROM users WHERE a = 3 db.users.find({a : 3}).explain()
UPDATE users SET a = 1 WHERE b = 2 db.users.update({b : 2}, {$set : {a : 1}}, false, true)
UPDATE users SET a = a + 2 WHERE b = 2 db.users.update({b : 2}, {$inc: {a : 2}}, false, true)
DELETE FROM users WHERE a = 3 db.users.remove({ a : 3})
DELETE FROM users db.users.remove()


MongoDB 中可用到的其它语句:

  • 存在某字段: db.users.find({a : {$exists : true}})

  • 不存在某字段: db.users.find({a : {$exists : false}})

  • 查询指定长度: db.users.find({name : {$size : 10}})

  • 查询字段是数组: db.users.find({name.first; : 'Joe', name.last : 'David'})


  • var cursor = db.users.find()
    while(cursor.hasNext()) printjson(curson.next())

  • db.users.find().forEach(printjson)

  • db.users.find().toArray()

2012年8月22日星期三

Gearman 安装及常见问题

Gearman 是分发任务的程序框架。因为它提供多语言 API ,所以可用于各场合,与 Hadoop 相比,Gearman 更偏向于任务分发和异步功能。Gearman 最初用于LiveJournal的图片 resize 功能。

安装


[bash]
# CXX=/usr/bin/g++44 CC=/usr/bin/gcc44 ./configure --prefix=/usr/local/gearman --enable-static-boost --with-mysql=/usr/local/mysql/bin/mysql_config
# make
# make install
[/bash]


安装 PHP 扩展


[bash]
[root@localdomain gearman-1.0.2]# /usr/local/php/bin/phpize
[root@localdomain gearman-1.0.2]# ./configure --with-php-config=/usr/local/php/bin/php-config --with-gearman=/usr/local/gearman/
[root@localdomain gearman-1.0.2]# make
[root@localdomain gearman-1.0.2]# make install
[/bash]
完后,修改 PHP 配置文件, 加入 gearman.so 扩展,重启 PHP,执行命令 php -i | grep gearman,若看到如下类似的信息,说明安装成功。
[bash]
[root@localdomain php]# bin/php -i | grep gearman
gearman
gearman support => enabled
libgearman version => 0.38
PWD => /usr/local/src/gearman-1.0.2
_SERVER["PWD"] => /usr/local/src/gearman-1.0.2
[/bash]

用 MySQL 做持久化存储,启动服务



  1. 在 MySQL 服务器中建立数据库和表结构:
    [sql]
    CREATE TABLE `gearman_queue` (
    `unique_key` varchar(64) NOT NULL,
    `function_name` varchar(255) DEFAULT NULL,
    `priority` int(11) DEFAULT NULL,
    `data` longblob,
    `when_to_run` int(11) DEFAULT NULL,
    PRIMARY KEY (`unique_key`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1
    [/sql]
    Gearman 的 MySQL 持久化储存,默认表名是 gearman_queue,这可在服务启动时根据需要进行设置。另外,表结构设置如存储引擎可根据效率等进行修改。

  2. 启动服务
    [bash]
    [root@localdomain gearman]# /usr/local/gearman/sbin/gearmand -p 4730 --log-file=/tmp/gearmand-4730.log --pid-file=/tmp/gearmand-4730.pid -q MySQL --mysql-host=localhost --mysql-user=gearmand --mysql-password=123456 --mysql-db=gearman --verbose DEBUG -d
    [/bash]
    若上一步中建立的数据库表,其表名不是 gearman_queue,用参数 --mysql-table=TABLE_NAME 进行指定即可。



命令行工具



  • 启动 Worker bin/gearman -w -f wc -- wc -l &

  • 运行 Client bin/gearman -f wc < /tmp/gearmand-4730.log

  • 查看 Server 状态 bin/gearadmin -h [ --host ] -p [--port] --status

  • 查看 Server 运行中的 workers bin/gearadmin -h [ --host ] -p [--port] --workers

  • 关闭 Server bin/gearadmin -h [ --host ] -p [--port] --shutdown

  • 移除名为 FUNCTION_NAME 的 JOB bin/gearman -n -w -f FUNCTION_NAME > /dev/null

  • 移除 20 个名为 FUNCTION_NAME 的 JOB gearman -c 20 -n -w -f FUNCTION_NAME > /dev/null




安装常见问题



  1. 编译时,报错:configure: error: cannot find Boost headers version >= 1.39.0
    [bash]
    [root@localdomain gearmand-0.38]# yum search boost
    [root@localdomain gearmand-0.38]# yum install boost.x86_64
    [root@localdomain gearmand-0.38]# yum install yum install boost-devel.x86_64
    [/bash]

  2. uuid/uuid.h;No such file or directory
    错误代码:
    [bash]
    [root@localdomain gearmand-0.38]# make
    make all-am
    make[1]: Entering directory `/usr/local/src/gearmand-0.38'
    CXX libgearman/libgearman_libgearman_la-add.lo
    libgearman/add.cc:53:23: error: uuid/uuid.h: No such file or directory
    libgearman/add.cc: In function 'gearman_task_st* add_task(gearman_client_st&, gearman_task_st*, void*, gearman_command_t, const gearman_string_t&, gearman_unique_t&, const gearman_string_t&, time_t, const gearman_actions_t&)':
    libgearman/add.cc:154: error: 'uuid_t' was not declared in this scope
    libgearman/add.cc:154: error: expected ';' before 'uuid'
    libgearman/add.cc:155: error: 'uuid' was not declared in this scope
    libgearman/add.cc:155: error: 'uuid_generate' was not declared in this scope
    libgearman/add.cc:156: error: 'uuid_unparse' was not declared in this scope
    libgearman/add.cc: In function 'gearman_task_st* add_reducer_task(gearman_client_st*, gearman_command_t, gearman_job_priority_t, const gearman_string_t&, const gearman_string_t&, const gearman_unique_t&, const gearman_string_t&, const gearman_actions_t&, time_t, void*)':
    libgearman/add.cc:263: error: 'uuid_t' was not declared in this scope
    libgearman/add.cc:263: error: expected ';' before 'uuid'
    libgearman/add.cc:334: error: 'uuid' was not declared in this scope
    libgearman/add.cc:334: error: 'uuid_generate' was not declared in this scope
    libgearman/add.cc:335: error: 'uuid_unparse' was not declared in this scope
    make[1]: *** [libgearman/libgearman_libgearman_la-add.lo] Error 1
    make[1]: Leaving directory `/usr/local/src/gearmand-0.34'
    make: *** [all] Error 2
    [/bash]
    yum 解决如下,或者源代码安装,参考 uuid/uuid.h;No such file or directory
    [bash]
    [root@localdomain gearmand-0.38]# yum install e4fsprogs.x86_64
    [root@localdomain gearmand-0.38]# yum install e2fsprogs-devel.x86_64
    [/bash]

  3. configure: error: Unable to find libevent
    [bash]
    [root@localdomain gearmand-0.38]# yum install libevent.x86_64
    [root@localdomain gearmand-0.38]# yum install libevent-devel.x86_64
    [/bash]

  4. tr1/cinttypes: No such file or directory
    错误代码:
    [bash gutter="false"]
    make[1]: Entering directory `/usr/local/src/gearmand-0.38'
    CXX libgearman/libgearman_libgearman_la-actions.lo
    In file included from ./libgearman/common.h:44,
    from libgearman/actions.cc:39:
    ./libgearman-1.0/gearman.h:53:27: error: tr1/cinttypes: No such file or directory
    make[1]: *** [libgearman/libgearman_libgearman_la-actions.lo] Error 1
    make[1]: Leaving directory `/usr/local/src/gearmand-0.38'
    [/bash]
    解决:
    [bash]
    [root@localdomain gearmand-0.38]# yum install gcc44 gcc44-c++
    [/bash]

  5. 用 MySQL 做 Gearman Server 的持久化存储,make install 时始终无法通过。最后直接将 libgearman-server/plugins/queue/mysql/queue.cc 文件中 include MySQL 库文件的位置改为绝对路径才算解决这个问题。

  6. [bash]
    #include </usr/local/mysql/include/mysql/mysql.h>
    #include </usr/local/mysql/include/mysql/errmsg.h>
    [/bash]

  7. Trouble compiling gearman 0.22 with drizzle persistence on Centos 5.6

  8. ./configure doesn't fail for lack of c++

  9. compiling gearmand tr1/cinttypes in cent os



说明:

  • 版本说明: gearmand 0.38 , libgearman

  • 系统为 64 位,所以之上的软件都是安装 64 位的版本,若系统不是 64 位的,修改对应的版本即是。

  • 用 yum 安装,可能会收到找不到对应源的错误,或无对应需要的版本。在 /etc/yum.repos.d/drizzle.repo 文件中加入如下,重新执行命令即可。
    [bash gutter="false"]
    [drizzle]
    name=drizzle
    baseurl=http://rpm.drizzle.org/7-dev/redhat/$releasever/$basearch/
    enabled=1
    gpgcheck=0

    [drizzle-src]
    name=drizzle-src
    baseurl=http://rpm.drizzle.org/7-dev/redhat/$releasever/source
    enabled=1
    gpgcheck=0

    [drizzle-dev]
    name=drizzle-dev
    baseurl=http://rpm.drizzle.org/7-dev/redhat/5/$basearch/
    enabled=0
    gpgcheck=0
    [/bash]

Hadoop 常见问题和说明


  1. Warning: $HADOOP_HOME is deprecated.
    执行 Hadoop 命令时,收到警告:
    [bash]
    [hduser@master hadoop]$ ./bin/hadoop
    Warning: $HADOOP_HOME is deprecated.
    [/bash]
    取消警告,设置环境变量 $HADOOP_HOME_WARN_SUPPRESS=1。更简便的方法是将环境变量加入到 shell 配置文件中,假设 shell 为 bash:
    [bash]
    vim $HOME/.bashrc
    export HADOOP_HOME_WARN_SUPPRESS=1
    [/bash]

  2. Name node is in safe mode.
    对 Hadoop 操作时,收到 Name node is in safe mode的提示, e.g.
    [bash]
    [hduser@master hadoop]$ hadoop fs -put word-input/ wordinput
    put: org.apache.hadoop.hdfs.server.namenode.SafeModeException: Cannot create directory /user/hduser/wordinput. Name node is in safe mode.
    [/bash]
    如想立即退出安全模式,直接执行 hadoop dfsadmin -safemode leave命令。

    Background:
    NameNode 在启动的时候首先进入安全模式,如果 DataNode 丢失的 blocks 达到一定的比例(1 - dfs.safemode.threshold.pct),则系统会一直处于安全模式状态即只读状态。
    dfs.safemode.threshold.pct (默认值为 0.999f,定义于 conf/hdfs-site.xml文件中),表示 HDFS 启动的时候, 如果 DataNode 上报的 blocks 个数达到最小备份级别 (默认是 1, 可以通过 dfs.replication.min 设置) blocks 个数的 0.999 倍 才可以离开安全模式,否则一直处于只读模式, 如果设为 1,则 HDFS 永远是处于 safemode, 而如果设为 0,NameNode 不会从安全模式启动。

    下面是来自某个 NameNode 启动时的日志,blocks 上报比例为 1 , 达到了阀值 0.999:

    The ratio of reported blocks 1.0000 has reached the threshold 0.9990. Safe mode will be turned off automatically in 18 seconds.


    从上面可知,除了执行命令 hadoop dfsadmin -safemode leave 强制退出外,修改 dfs.safemode.threshold.pct 为较小的值也可退出安全模式。

    操作安全模式下的命令: hadoop dfsadmin -safemode [value]

    • enter 进入安全模式。

    • leave 强制 NameNode 离开安全模式。

    • get 返回安全模式是否开启的信息。

    • wait 等待,一直到安全模式结束。



  3. Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out
    Hadoop 运行时需要打开多个文件进行分析,系统一般默认是 1024(ulimit -a可查看),正常情况下这个大小已经足够,但在 Hadoop 处理大数据量时来说,这还不够大。解决办法,需修改两个文件:

    1. 文件 /etc/security/limits.conf:
      [bash]
      vim /etc/security/limits.conf
      #加上
      * soft nofile 102400
      * hard nofile 409600
      [/bash]

    2. 文件 /etc/pam.d/login
      [bash]
      # 32 位机器加上
      session required /lib/security/pam_limits.so
      # 64 位机器加上
      session required /lib64/security/pam_limits.so
      [/bash]



  4. Too many fetch-failures
    出现这个错误,表明 cluster 结点间的连接出现问题。

    1. 检查所有节点的 /etc/hosts, 除了本机 IP 需要对应 服务器名外,还要包含 cluster 中所有结点的 IP 和 服务器名。

    2. 检查 $HOME/.ssh/authorized_keys,要求包含访问用户的public key





  5. job 执行时,map 快,但是 reduce 很慢,且反复出现 reduce=0%
    修改 conf/hadoop-env.shexport HADOOP_HEAPSIZE=4000

  6. 能够启动 DataNode,但无法访问,也无法结束。
    在重新格式化一个新的分布式文件时,需要将 NameNode 上所配置的 dfs.name.dir 这一 NameNode 用来存放 NameNode 持久存储名字空间及事务日志的本地文件系统路径删除,同时将各 DataNode 上的 dfs.data.dir 的路径 DataNode 存放块数据的本地文件系统路径的目录也删除。这是因为 Hadoop 在格式化一个新的分布式文件系统时,每个存储的名字空间都对应了建立时间的那个版本(可查看/tmp/hadoop/dfs/name/current/VERSION目录下的 VERSION 文件,上面记录了版本信息),所以在重新格式化新的分布式系统文件时,最好先删除 name 目录。同时,也必须删除所有 DataNode 的 dfs.data.dir 指定的目录。这样才可以使 NameNode 和 DataNode 的版本信息对应。注意:删除很危险!

  7. java.io.IOException: Could not obtain block: blk_*********_*** file=/user/hduser/warehouse/src_***_log/src_***_log
    出现这种情况大多是没有连接上结点。

  8. java.lang.OutOfMemoryError: Java heap space
    出现这种异常,是 jvm 内存不够得,需修改所有的 DataNode 的 jvm 内存大小。
    [bash gutter="false"]
    Java -Xms1024m -Xmx4096m
    [/bash]
    一般 jvm 的最大内存使用应该为总内存大小的一半,若内存为 8G ,所以设置为 4096M ,这一值可能依旧不是最优的值。(其实最好设置为真实物理内存大小的 0.8)

  9. map 100 %,reduce 到 98% 左右时,job 直接进 failed
    检查 mapred.map.tasks是不是设置过大,设置太大的话会导致处理大量的小文件。另外,还需检查 mapred.reduce.parallel.copies 是否设置合适。

  10. hadoop.tmp.dir
    hadoop.tmp.dir 修改后,master 需要 hadoop namenode -format 重新将 HDFS 格式化,且需要删除从库的 hadoop.data.dir 数据目录。


  11. dfs.replication 和 dfs.block.size
    dfs.replication 表示数据备份的数量,默认是 3dfs.block.size,block 的大小,单位字节,它必须是必须是 512 的倍数,因为采用 crc 作文件完整性交验,默认配置 512 是 checksum 的最小单元。

  12. ipc.Client: Retrying connect to server: localhost/127.0.0.1:54310. Already tried

    • 这可能是由于 HDFS format 失败引起的,format 失败的原因可能是用户对 hadoop.tmp.dir 目录的权限不够,可以执行
      [bash]
      # 假设 hadoop.tmp.dirvalue 为 /tmp/hadoop
      $ sudo chown -R hduser /tmp/hadoop
      [/bash]


    • [bash gutter="false"]
      [hduser@hadoop hadoop]# hadoop fs -ls
      12/08/01 15:14:51 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 0 time(s).
      12/08/01 15:14:52 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 1 time(s).
      12/08/01 15:14:53 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 2 time(s).
      12/08/01 15:14:54 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 3 time(s).
      12/08/01 15:14:55 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 4 time(s).
      12/08/01 15:14:56 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 5 time(s).
      12/08/01 15:14:57 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 6 time(s).
      12/08/01 15:14:58 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 7 time(s).
      12/08/01 15:14:59 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 8 time(s).
      12/08/01 15:15:00 INFO ipc.Client: Retrying connect to server: hadoop.master/192.168.0.3:54310. Already tried 9 time(s).
      Bad connection to FS. command aborted. exception: Call to hadoop.master/192.168.0.3:54310 failed on connection exception: java.net.ConnectException: Connection refused
      [/bash]
      服务未启动。master 上执行命令启动服务:
      [bash]
      [hduer@master /usr/local/hadoop]$ bin/start-hdfs.sh
      [/bash]






References:

2012年8月5日星期日

Running Hadoop (Multi-Node Cluster)

FROM: Running Hadoop On Ubuntu Linux (Multi-Node Cluster)



Structure


这里,使用两台主机来搭建多节点的 Hadoop cluster。最简单的方法是,先将两台主机都搭建好单节点的 Hadoop,然后将其一台设为 master (因为只有两台主机,所以也将其同时设为 slave),另外一台为 slave。


Tutorial approach and structure.




准备


Configuring single-node cluster first

参看 Running Hadoop (Single-Node Cluster)。推荐两台主机都采用相同设置,如安装目录,JAVA 环境,配置等等。

在开始下面的配置前,停止两台主机上的 Single-node cluster。

Networking

这里,最重要的一点是用于测试的两台主机能相互访问。为了方便,master 的 IP 地址设为192.168.0.1slave 的 IP 地址为 192.168.0.2,更新两台主机的 /etc/hosts 文件:
[bash gutter="false"]
#/etc/hosts (for master AND slave)
192.168.0.1 master
192.168.0.2 slave
[/bash]

SSH access

master 主机上的 hduser 帐号必须能通过 SSH 在不需要密码的情况下访问本机和 slave (ssh -h localhost -u hduser, ssh -h slave -u hduser)。如果有参照 Running Hadoop (Single-Node Cluster),则只需将 hduser@master 的 public SSH key ($HOME/.ssh/id_rsa.pbu)复制到 hduser@slaveauthorized_keys ($HOME/.ssh/authorized_keys)文件中,或者使用如下 SSH 命令:
[bash]
[hduser@master ~]$ ssh-copy-id -i $HOME/.ssh/id_rsa.pub hduser@slave
[/bash]
上面命令执行时提示输入 huser@slave 的登录密码,然后再复制 public SSH keys 到 $HOME/.ssh/authorized_keys

最后一步检测 master 主机上 hduser 访问 master,slave :

master to master
[bash gutter="false"]
[hduser@master ~]$ ssh master
The authenticity of host 'master (192.168.0.1)' can't be established.
RSA key fingerprint is 3b:21:b3:c0:21:5c:7c:54:2f:1e:2d:96:79:eb:7f:95.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'master' (RSA) to the list of known hosts.
Linux master 2.6.20-16-386 #2 Thu Jun 7 20:16:13 UTC 2007 i686
...
[hduser@master ~]$
[/bash]

master to slave:
[bash gutter="false"]
[hduser@master ~]$ ssh slave
The authenticity of host 'slave (192.168.0.2)' can't be established.
RSA key fingerprint is 74:d7:61:86:db:86:8f:31:90:9c:68:b0:13:88:52:72.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'slave' (RSA) to the list of known hosts.
Ubuntu 10.04
...
[hduser@slave ~]$
[/bash]

Hadoop


Cluster overview

下面内容介绍怎么配置一台座做 master ,一台做为 slave 的 多节点 Hadoop cluster。为了测试多节点间的数据传输和处理,而这里只有两台主机,所以,master 主机同时也会做为 一个 slave 节点。


How the final multi-node cluster will look like.



master 节点在 HDFS 和 MapReduce layer 分别运行一「master」的 daemon,HDFS 存储层的名为 NameNode,而 MapReduce 处理层的名为 JobTracker。两台主机同时运行着为「slave」的 daemons,HDFS 层的名为 DataNode, MapReduce 层的名为 TaskTracker。简单的来说,「master」 daemon 负责协调和管理,「slave」daemon 则是负责实际性的数据存储和处理工作。

Masters vs Slaves

From the Hadoop 1.x documentation:
Typicaly one machine in the cluster is designed as the NameNode and another machine the as JobTracker, exclusively. These are the actual "master nodes". The rest of the machines in the cluster act as both DataNode and TaskTracker. These are the slaves or "worker nodes".


Configuration


  1. conf/masters(master only)
    conf/masters 文件定义多节点的 Hadoop cluster 中哪台主机将启动 secondary NameNode。在这里的示例中,即 master 主机。primary NameNode 和 JobTracker 运行的主机,则取决于在哪台主机上运行 bin/start-dfs.shbin/start-mapred.sh 脚本 (而如果运行的是 bin/start-all.sh 脚本,则primary NameNode 和 JobTracker 将会运行于同一台主机上)。注意也可以通过运行 bin/hadoop-daemon.sh start [namenode | secondarynamenode | datanode | jobtracker | tasktracker] 来手动启动 Hadoop daemon,这个时候,配置文件 conf/mastersconf/slaves 将不会被加载。

    下面是来自 Hadoop HDFS user guider的一些关于 conf/masters 的详细信息:
    The secondary NameNode merges the fsimage and the edits log files periodically and keeps edits log size within a limit. It is usually run on a different machine than the primary NameNode since its memory requirements are on the same order as the primary NameNode. The secondary NameNode is started by bin/start-dfs.sh on the nodes specified in conf/masters file.


    重申一遍的是,哪台主机执行 bin/start-dfs.sh 脚本,哪台主机就是 primary NameNode.

    按照如下类似规则更新 masterconf/masters
    [bash gutter="false"]
    master
    [/bash]

  2. conf/slaves (master only)
    conf/slaves 中列出 Hadoop cluster 中的 slave daemons(DataNodes 和 TaskTrackers) 所在的主机,每行对应一个。示例中,为了让两台主机都处理和存储数据,所以 masterslave 都会被做为 Hadoop slave。

    按照如下规则更新 master 主机上的 conf/slaves :
    [bash gutter="false"]
    master
    slave
    [/bash]

    如果 cluster 中还有其它的 slave 节点,按如下方式直接将其加入 conf/slaves 文件即可:
    [bash]
    master
    slave
    anotherslave01
    anotherslave02
    anotherslave03
    [/bash]
    Note: master 主机上的 conf/slaves 文件只有运行 bin/start-dfs.hbin/stop-dfs.sh 脚本时才会起作用。例如,如果想在处于运行状态中的 cluster 中加入一新的 DataNode, 直接在新的 slave 主机上运行 bin/start-daemon.sh start datanode 即可。而使用 conf/slaves则是为了方便统一管理 cluster, 例如重启。The conf/slaves file on master is used only by the scripts like bin/start-dfs.sh or bin/stop-dfs.sh. For example, if you want to add DataNodes on the fly(which is not described in this tutorial yet), you can "manually" start the DataNode daemon on a new slave machine via bin/hadoop-daemon.sh start daemon. Using the conf/slaves file on the master simply helps you to make "full" cluster restarts easier.


  3. conf/*-site.xml(all machines)
    Note: As of Hadoop 0.20.x and 1.x, the configuration settings previously found in hadoop-site.xml were moved to conf/core-site.xml(fs.default.name), conf/mapred-site.xml(mapred.job.tracker) and conf/hdfs-site.xml(dfs.replication).


    如果之前已参照 single-node cluster配置 cluster 中的所有主机为 single-node, 则只需要修改几个配置选项即可:

    Important: You have to change the configuration files conf/core-site.xml, conf/mapred-site.xml and conf/hdfs-site.xml on ALL machines as follows.

    第一步,修改 conf/core-site.xml 中的 fs.default.name 选项,它用来指定 NameNode (the HDFS master) host 和 port。示例中,是 master 主机:
    [bash gutter="false"]
    <!-- In: conf/core-site.xml -->
    <property>
    <name>fs.default.name</name>
    <value>hdfs://master:54310</value>
    <description>The name of the default file system. A URI whose
    scheme and authority determine the FileSystem implementation. The
    uri's scheme determines the config property (fs.SCHEME.impl) naming
    the FileSystem implementation class. The uri's authority is used to
    determine the host, port, etc. for a filesystem.</description>
    </property>
    [/bash]

    第二步,修改 conf/mapred-site.xml 文件中 mapred.job.tracker 选项,它用来指定 JobTracker (MapReduce master) host 和 port,这里示例中,同样是 master 主机。
    [bash gutter="false"]
    <!-- In: conf/mapred-site.xml -->
    <property>
    <name>mapred.job.tracker</name>
    <value>master:54311</value>
    <description>The host and port that the MapReduce job tracker runs
    at. If "local", then jobs are run in-process as a single map
    and reduce task.
    </description>
    </property>
    [/bash]

    第三部,修改 conf/hdfs-site.xml 文件中表示默认的块复制数 dfs.replication 选项,它用来定义对于每个单个文件将会有多少台主机保留其备份。如果该定义的值大于 cluster 中的 slave 节点数(即 DataNodes 总数),日志文件中将会出现很多类似于 (Zero targets found, forbidden1.size=1) 的错误。

    dfs.replication 的默认值为 3。这里,因为只有 2 个 slaves 节点,所以将其修改为 2:
    [bash gutter="false"]
    <!-- In: conf/hdfs-site.xml -->
    <property>
    <name>dfs.replication</name>
    <value>2</value>
    <description>Default block replication.
    The actual number of replications can be specified when the file is created.
    The default is used if replication is not specified in create time.
    </description>
    </property>
    [/bash]

  4. Additional settings
    Hadoop API Overview(页面底部)有列出其它值得注意的配置选项:

    文件conf/mapred-site.xml:

    • mapred.local.dir Determines where temporary MapReduce data is written. It also may be a list of directories.

    • mapred.map.tasks As a rule of thumb, use 10x the number of slaves(i.e., the number of TaskTrackers).

    • mapred.reduce.tasks As a rul the thumb, use 2x the number of slave processors(i.e., number of TaskTrackers).





Formatting the HDFS filesystem via the NameNode

在启动新的 Hadoop cluster 前,首先需要格式化 Hadoop 中的 HDFS 的 NameNode。注意,不要格式化处于运行中的 Hadoop,否则 HDFS 中的所有数据将会丢失。

格式化 HDFS ,实际就是初始化 dfs.name.dir 指定的目录。命令如下:
[bash]
[hduser@master /usr/local/hadoop]$ bin/hadoop namenode -format
... INFO dfs.Storage: Storage directory /tmp/hadoop/dfs/name has been successfully formatted.
[hduser@master /usr/local/hadoop]$
[/bash]
Background: HDFS 的 name table 是存储于 NameNode 的dfs.name.dir指定的本地文件系统中。NameNode 用 name table 来保存追踪和协调所有 DataNodes 的信息。 The HDFS name table is stored on the NameNode's local filesystem in the directory specified by dfs.name.dir. The name table is used by the NameNode to store tracking and coordination information for the DataNaode.

Starting the multi-node cluster

启动 cluster 包括两个步骤。第一 , 启动 HDFS daemon,即启动 master 上的 NameNode daemon 和 所有 slaves(这里包括 masterslave) 上的 DataNode daemons;第二,启动 MapReduce,即 master 上的 JobTracker daemon 和 所有 slaves(这里包括 masterslave) 上的 TaskTracker daemons。


  1. HDFS daemon
    想让哪台主机做为 primary NameNode,就在哪台主机上运行 bin/start-dfs.sh,同时,conf/slaves 中列出的主机就会做为 DataNodes。

    这里示例中,master 上执行 bin/start-dfs.sh:
    [bash gutter="false"]
    [hduser@master /usr/local/hadoop]$ bin/start-dfs.sh
    starting namenode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-namenode-master.out
    slave: Ubuntu 10.04
    slave: starting datanode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-datanode-slave.out
    master: starting datanode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-datanode-master.out
    master: starting secondarynamenode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-secondarynamenode-master.out
    [hduser@master /usr/local/hadoop]$
    [/bash]

    slave上,通过查看 logs/hadoop-hduser-datanode.slave.log 日志文件可知晓启动是否成功。
    [bash gutter="false"]
    ... INFO org.apache.hadoop.dfs.Storage: Storage directory /tmp/hadoop/dfs/data is not formatted.
    ... INFO org.apache.hadoop.dfs.Storage: Formatting ...
    ... INFO org.apache.hadoop.dfs.DataNode: Opened server at 50010
    ... INFO org.mortbay.util.Credential: Checking Resource aliases
    ... INFO org.mortbay.http.HttpServer: Version Jetty/5.1.4
    ... INFO org.mortbay.util.Container: Started org.mortbay.jetty.servlet.WebApplicationHandler@17a8a02
    ... INFO org.mortbay.util.Container: Started WebApplicationContext[/,/]
    ... INFO org.mortbay.util.Container: Started HttpContext[/logs,/logs]
    ... INFO org.mortbay.util.Container: Started HttpContext[/static,/static]
    ... INFO org.mortbay.http.SocketListener: Started SocketListener on 0.0.0.0:50075
    ... INFO org.mortbay.util.Container: Started org.mortbay.jetty.Server@56a499
    ... INFO org.apache.hadoop.dfs.DataNode: Starting DataNode in: FSDataset{dirpath=' /tmp/hadoop/dfs/data/current'}
    ... INFO org.apache.hadoop.dfs.DataNode: using BLOCKREPORT_INTERVAL of 3538203msec
    [/bash]

    从上面的 slave的日志文件可看出,它有格式化 dfs.data.dir 指定的存储目录 。而如果这个目录在格式化之前不存在,它就会自动创建。

    在这个时候,master 上下面的 JAVA 进程应该是处于运行中。
    [bash]
    [hduser@master /usr/local/hadoop]$ jps
    14799 NameNode
    15314 Jps
    14880 DataNode
    14977 SecondaryNameNode
    [hduser@master /usr/local/hadoop]$
    [/bash]
    slave 上运行的则是:
    [bash]
    [hduser@slave /usr/local/hadoop]$ jps
    15183 DataNode
    15616 Jps
    [hduser@slave /usr/local/hadoop]$
    [bash]
    </li>
    <li>MapReduce daemons
    哪台主机上上运行 JobTracker,就在哪台主机上运行 <code>bin/start-mapred.sh</code>,这样同时,<code>conf/slaves</code> 文件中列出的主机就会运行 TaskTrackers。

    这里示例中, <code>master</code> 上运行 <code>bin/start-mapred.sh</code>:
    [bash gutter=false]
    [hduser@master /usr/local/hadoop]$ bin/start-mapred.sh
    starting jobtracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hadoop-jobtracker-master.out
    slave: Ubuntu 10.04
    slave: starting tasktracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-tasktracker-slave.out
    master: starting tasktracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-tasktracker-master.out
    [hduser@master /usr/local/hadoop]$
    [/bash]

    slave 上,查看 logs/hadoop-hduser-tasktracker-slave.log 检测启动是否成功。
    [bash gutter="false"]
    ... INFO org.mortbay.util.Credential: Checking Resource aliases
    ... INFO org.mortbay.http.HttpServer: Version Jetty/5.1.4
    ... INFO org.mortbay.util.Container: Started org.mortbay.jetty.servlet.WebApplicationHandler@d19bc8
    ... INFO org.mortbay.util.Container: Started WebApplicationContext[/,/]
    ... INFO org.mortbay.util.Container: Started HttpContext[/logs,/logs]
    ... INFO org.mortbay.util.Container: Started HttpContext[/static,/static]
    ... INFO org.mortbay.http.SocketListener: Started SocketListener on 0.0.0.0:50060
    ... INFO org.mortbay.util.Container: Started org.mortbay.jetty.Server@1e63e3d
    ... INFO org.apache.hadoop.ipc.Server: IPC Server listener on 50050: starting
    ... INFO org.apache.hadoop.ipc.Server: IPC Server handler 0 on 50050: starting
    ... INFO org.apache.hadoop.mapred.TaskTracker: TaskTracker up at: 50050
    ... INFO org.apache.hadoop.mapred.TaskTracker: Starting tracker tracker_slave:50050
    ... INFO org.apache.hadoop.ipc.Server: IPC Server handler 1 on 50050: starting
    ... INFO org.apache.hadoop.mapred.TaskTracker: Starting thread: Map-events fetcher for all reduce tasks on tracker_slave:50050
    [/bash]

    这个时候, master 上应该有下列 JAVA 进程:
    [bash]
    [hduser@master /usr/local/hadoop]$ jps
    16017 Jps
    14799 NameNode
    15686 TaskTracker
    14880 DataNode
    15596 JobTracker
    14977 SecondaryNameNode
    [hduser@master /usr/local/hadoop]$
    [/bash]
    slave 上:
    [bash]
    [hduser@slave /usr/local/hadoop]$ jps
    15183 DataNode
    15897 TaskTracker
    16284 Jps
    [hduser@slave /usr/local/hadoop]$
    [/bash]



Stopping the multi-node cluster

跟启动相似,停止 cluster 也包括两个步骤。流程正好跟启动时相反,第一,停止 MapReduce deamon,即master 上的 JobTracker 和所有 slaves(这里包括 masterslave) 上的 TaskTrackers。第二步,停止 HDFS daemons,即 master 上的 NameNode daemon 和所有 slaves(这里包括 masterslave) 上的 DataNode deamons。


  1. MapReduce daemons
    在运行 JobTracker 的主机上执行 bin/stop-mapred.sh,这不仅不会停止 MapReduce cluster 中的 JobTracker daemon ,也会停止 conf/slaves 中列出的主机上的 TaskTracker daemons。

    在这里示例中,master 上运行 bin/stop-mapred.sh
    [bash]
    [hduser@master /usr/local/hadoop]$ bin/stop-mapred.sh
    stopping jobtracker
    slave: Ubuntu 10.04
    master: stopping tasktracker
    slave: stopping tasktracker
    [hduser@master /usr/local/hadoop]$
    [/bash]

    这个时候,master 上运行的 JAVA 进程是:
    [bash]
    [hduser@master /usr/local/hadoop]$ jps
    14799 NameNode
    18386 Jps
    14880 DataNode
    14977 SecondaryNameNode
    [hduser@master /usr/local/hadoop]$
    [/bash]

    slave 上:
    [bash]
    [hduser@slave /usr/local/hadoop]$ jps
    15183 DataNode
    18636 Jps
    [hduser@slave /usr/local/hadoop]$
    [/bash]

  2. HDFS daemons
    在运行 NameNode 的主机上运行 bin/stop-dfs.sh 。执行这个命令,不仅会停止 NameNode daemon,也不会停止 conf/slaves 文件中列出的所有主机上的 DataNodes。

    这里示例中,即在 master 上运行 bin/stop-dfs.sh
    [bash]
    [hduser@master /usr/local/hadoop]$ bin/stop-dfs.sh
    stopping namenode
    slave: Ubuntu 10.04
    slave: stopping datanode
    master: stopping datanode
    master: stopping secondarynamenode
    [hduser@master /usr/local/hadoop]$
    [/bash]

    这个时候,master 上有运行的 Java 进程是:
    [bash]
    [hduser@master /usr/local/hadoop]$ jps
    18670 Jps
    [hduser@master /usr/local/hadoop]$
    [/bash]

    slave 上:
    [bash]
    [hduser@slave /usr/local/hadoop]$jps
    18894 Jps
    [hduser@slave /usr/local/hadoop]$
    [/bash]




Running a MapReduce job

按照 single-node cluster tutorial. 中描述的 Running a MapReduce job即可。


建议使用大数据集,这样在 masterslave上都会执行 Map 和 Reduce tasks。下面列出了 Gutenburg Project 上用于测试的电子书文档,包括之前 single-node 测试中提到的三个文档。


下载上述文件的 Plain Text utf8 版本,复制到 HDFS 中,在 master 上执行 WordCount 的 MapReduce job,然后在 HDFS 查看 job 的运行结果。

下面是在 master 上的一个示例 job 输出:
[bash gutter="false"]
[hduser@master /usr/local/hadoop]$ bin/hadoop jar hadoop*examples*.jar wordcount /user/hduser/gutenberg /user/hduser/gutenberg-output
... INFO mapred.FileInputFormat: Total input paths to process : 7
... INFO mapred.JobClient: Running job: job_0001
... INFO mapred.JobClient: map 0% reduce 0%
... INFO mapred.JobClient: map 28% reduce 0%
... INFO mapred.JobClient: map 57% reduce 0%
... INFO mapred.JobClient: map 71% reduce 0%
... INFO mapred.JobClient: map 100% reduce 9%
... INFO mapred.JobClient: map 100% reduce 68%
... INFO mapred.JobClient: map 100% reduce 100%
.... INFO mapred.JobClient: Job complete: job_0001
... INFO mapred.JobClient: Counters: 11
... INFO mapred.JobClient: org.apache.hadoop.examples.WordCount$Counter
... INFO mapred.JobClient: WORDS=1173099
... INFO mapred.JobClient: VALUES=1368295
... INFO mapred.JobClient: Map-Reduce Framework
... INFO mapred.JobClient: Map input records=136582
... INFO mapred.JobClient: Map output records=1173099
... INFO mapred.JobClient: Map input bytes=6925391
... INFO mapred.JobClient: Map output bytes=11403568
... INFO mapred.JobClient: Combine input records=1173099
... INFO mapred.JobClient: Combine output records=195196
... INFO mapred.JobClient: Reduce input groups=131275
... INFO mapred.JobClient: Reduce input records=195196
... INFO mapred.JobClient: Reduce output records=131275
[hduser@master /usr/local/hadoop]$
[/bash]

slave 上 datanode...
[bash gutter="false"]
# from logs/hadoop-hduser-datanode-slave.log on slave
... INFO org.apache.hadoop.dfs.DataNode: Received block blk_5693969390309798974 from /192.168.0.1
... INFO org.apache.hadoop.dfs.DataNode: Received block blk_7671491277162757352 from /192.168.0.1
<<>>
... INFO org.apache.hadoop.dfs.DataNode: Served block blk_-7112133651100166921 to /192.168.0.2
... INFO org.apache.hadoop.dfs.DataNode: Served block blk_-7545080504225510279 to /192.168.0.2
... INFO org.apache.hadoop.dfs.DataNode: Served block blk_-4114464184254609514 to /192.168.0.2
... INFO org.apache.hadoop.dfs.DataNode: Served block blk_-4561652742730019659 to /192.168.0.2
<<>>
... INFO org.apache.hadoop.dfs.DataNode: Received block blk_-2075170214887808716 from /192.168.0.2 and mirrored to /192.168.0.1:50010
... INFO org.apache.hadoop.dfs.DataNode: Received block blk_1422409522782401364 from /192.168.0.2 and mirrored to /192.168.0.1:50010
... INFO org.apache.hadoop.dfs.DataNode: Deleting block blk_-2942401177672711226 file /tmp/hadoop/dfs/data/current/blk_-2942401177672711226
... INFO org.apache.hadoop.dfs.DataNode: Deleting block blk_-3019298164878756077 file /tmp/hadoop/dfs/data/current/blk_-3019298164878756077
[/bash]

slave 上 tasktracker...
[bash gutter="false"]
# from logs/hadoop-hduser-tasktracker-slave.log on slave
... INFO org.apache.hadoop.mapred.TaskTracker: LaunchTaskAction: task_0001_m_000000_0
... INFO org.apache.hadoop.mapred.TaskTracker: LaunchTaskAction: task_0001_m_000001_0
... task_0001_m_000001_0 0.08362164% hdfs://master:54310/user/hduser/gutenberg/ulyss12.txt:0+1561677
... task_0001_m_000000_0 0.07951202% hdfs://master:54310/user/hduser/gutenberg/19699.txt:0+1945731
<<>>
... task_0001_m_000001_0 0.35611463% hdfs://master:54310/user/hduser/gutenberg/ulyss12.txt:0+1561677
... Task task_0001_m_000001_0 is done.
... task_0001_m_000000_0 1.0% hdfs://master:54310/user/hduser/gutenberg/19699.txt:0+1945731
... LaunchTaskAction: task_0001_m_000006_0
... LaunchTaskAction: task_0001_r_000000_0
... task_0001_m_000000_0 1.0% hdfs://master:54310/user/hduser/gutenberg/19699.txt:0+1945731
... Task task_0001_m_000000_0 is done.
... task_0001_m_000006_0 0.6844295% hdfs://master:54310/user/hduser/gutenberg/132.txt:0+343695
... task_0001_r_000000_0 0.095238104% reduce > copy (2 of 7 at 1.68 MB/s) >
... task_0001_m_000006_0 1.0% hdfs://master:54310/user/hduser/gutenberg/132.txt:0+343695
... Task task_0001_m_000006_0 is done.
... task_0001_r_000000_0 0.14285716% reduce > copy (3 of 7 at 1.02 MB/s) >
<<>>
... task_0001_r_000000_0 0.14285716% reduce > copy (3 of 7 at 1.02 MB/s) >
... task_0001_r_000000_0 0.23809525% reduce > copy (5 of 7 at 0.32 MB/s) >
... task_0001_r_000000_0 0.6859089% reduce > reduce
... task_0001_r_000000_0 0.7897389% reduce > reduce
... task_0001_r_000000_0 0.86783284% reduce > reduce
... Task task_0001_r_000000_0 is done.
... Received 'KillJobAction' for job: job_0001
... task_0001_r_000000_0 done; removing files.
... task_0001_m_000000_0 done; removing files.
... task_0001_m_000006_0 done; removing files.
... task_0001_m_000001_0 done; removing files.
[/bash]

如果想查看 job 的运行结果,参照 Running a MapReduce job 中 retrieve the job result from HDFS 步骤。

Caveats


  1. java.io.IOException: Incompatible namespaceIDs
    如果在 DataNode 的日志文件 (logs/hadoop-hduser-datanode-.log) 中看到 java.io.IOException: Incompatible namespaceIDs 这样的错误,有可能是 HDFS-107(之前名为 HADOOP-1212) 中提到的问题。

    错误的全部信息类似如下:
    [bash gutter="false"]
    ... ERROR org.apache.hadoop.dfs.DataNode: java.io.IOException: Incompatible namespaceIDs in /tmp/hadoop/dfs/data: namenode namespaceID = 308967713; datanode namespaceID = 113030094
    at org.apache.hadoop.dfs.DataStorage.doTransition(DataStorage.java:281)
    at org.apache.hadoop.dfs.DataStorage.recoverTransitionRead(DataStorage.java:121)
    at org.apache.hadoop.dfs.DataNode.startDataNode(DataNode.java:230)
    at org.apache.hadoop.dfs.DataNode.(DataNode.java:199)
    at org.apache.hadoop.dfs.DataNode.makeInstance(DataNode.java:1202)
    at org.apache.hadoop.dfs.DataNode.run(DataNode.java:1146)
    at org.apache.hadoop.dfs.DataNode.createDataNode(DataNode.java:1167)
    at org.apache.hadoop.dfs.DataNode.main(DataNode.java:1326)
    [/bash]
    下面是两种解决办法:

    • Workaround 1: Start from scratch
      这个方法作者自己已经测试过,但是这个方法比较麻烦且有一些不好的结果。步骤:

      1. 停止 cluster

      2. 删除有问题的 DataNode 的数据目录,即 conf/hdfs-site.xmldfs.data.dir 指定的目录。在这里的示例中,应该是 /tmp/hadoop/dfs/data 目录。

      3. 重新格式化 NameNode (注意:这个步骤后, HDFS 的数据将都会丢失!)

      4. 重启 cluster



    • Workaround2: Updating namespacID of problematic DataNodes
      这个是由 Jared Stehler 提出的解决方法,原作者没有做过测试。这个解决的方法修改到的地方比较少,仅仅只需修改有问题的 DataNode 上的一文件。

      1. 停止 DataNode

      2. 修改 /current/VERSIONnamespaceID 值为当前 NameNode 的值。

      3. 重启 DataNode



      示例中,应该是下面的相关文件:

      • NameNode: /tmp/hadoop/dfs/name/current/VERSION

      • DataNode: /tmp/hadoop/dfs/data/current/VERSION(Background: dfs.data.dir${hadoop.tmp.dir}/dfs/data)



      下面是一个 VERSION 中的内容:
      [bash gutter="false"]
      # contents of /current/VERSION
      namespaceID=393514426
      storageID=DS-1706792599-10.10.10.1-50010-1204306713481
      cTime=1215607609074
      storageType=DATA_NODE
      layoutVersion=-13
      [/bash]